一.基本认识
二.hello,mybatis
2.1 导包
- mybatis核心包
mybatis/mybatis-3.2.1.jar
- mybatis的依赖包
mybatis/lib/*.jar
- jdbc驱动包
mysql-connector-java-5.1.26-bin.jar
2.2 基本准备(表,domain)
public class Product {
private Long id;
//产品名称
private String productName;
//成本价
private Double costPrice;
//销售价格
private Double salePrice;
//供应商
private String supplier;
//品牌
private String brand;
//折扣
private Double cutoff;
//产品类型
private Long dir_id;
//省略getter,setter与toString...
}
2.3 创建配置文件
配置文件的位置要注意
jdbc.properties:数据库的参数
jdbc.driver=com.MysqL.jdbc.Driver
jdbc.url=jdbc:MysqL:///mybatis
jdbc.username=root
jdbc.password=123456
mybatis-config.xml:mybatis的核心配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- configuration:配置(xml的一个根)-->
<configuration>
<!--引入jdbc.propeties文件-->
<properties resource="jdbc.properties" />
<!--
environments:环境(多个环境)
default="development":多个环境中默认使用的是哪一个环境
-->
<environments default="development">
<!--
environment:某一个环境 id:就是这个环境的名称
-->
<environment id="development">
<!--
transactionManager:事务管理(ACID)
type="JDBC|MANAGED" jdbc:简单jdbc事务 MANAGED:啥都不做
-->
<transactionManager type="JDBC"/>
<!-- 数据源(连接池) POOLED:mybatis内置的连接池 -->
<dataSource type="POOLED">
<!--四大金刚:驱动,地址,用户名,密码-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--引入(找到)写sql的XML-->
<mapper resource="cn/itsource/dao/ProductMapper.xml"/>
</mappers>
</configuration>
ProductMapper.xml:sql语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
mapper:根(每个xml都得有,不用管它的含义)
namespace:命名空间(随便取个名称)
-->
<mapper namespace="cn.itsource.dao.ProductMapper">
<!--
select:代表这是一个查询语句
id:代表这个查询语句的唯一命名
以后你要找到这条sql: namespace+id
例:cn.itsource.dao.ProductMapper.getone
parameterType:参数类型
long -> Long _long -> long
resultType:返回的每一条结果的类型
注:返回类型的全限定名
-->
<select id="getone" parameterType="long" resultType="cn.itsource.domain.Product">
select * from product where id = #{id}
</select>
</mapper>
2.4 测试
/**
* ①. 想办法搞到核心配置文件 mybatis-config.xml
* ②. 获取到它的核心对象 sqlSession【相当于是咱们JPA中的EntityManager对象】
* EntityManagerFactory -> EntityManager
* sqlSessionFactoryBuilder -> sqlSessionFactory -> sqlSession
* ③.sqlSession就可以CRUD..
*/
@Test
public void testHello() throws Exception{
//①. 想办法搞到核心配置文件 mybatis-config.xml
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//②.获取到它的核心对象 sqlSession
// 2.1获到到sqlSessionFactory对象
sqlSessionFactoryBuilder builder = new sqlSessionFactoryBuilder();
sqlSessionFactory factory = builder.build(reader);
// 2.2获取到它的核心对象 sqlSession
sqlSession session = factory.openSession();
//③.获取到一个对象
/**
* String statement : 获取sql的字符串 namespace+id
* Object parameter : 参数传递
*/
Product product = session.selectOne("cn.itsource.dao.ProductMapper.getone",1L);
System.out.println(product);
//关闭session
session.close();
}
三.工具类与CRUD
3.1 准备MyBatisUtil
- sqlSessionFactoryBuilder:只用于创建factory,用完就可以扔掉
- sqlSessionFactory:重级量对象,创建后不要随便销毁(一个项目一个这个对象即可)
- sqlSession :用于完成咱们的CRUD
/**
* MyBatis的工具类,主要就是为我们创建sqlSession对象
*/
public class MyBatisUtil {
//定义一个sqlSessionFactory对象
/**
* 一个对象写这个位置,而且是静态的,它是有线程安全问题的
*/
private static sqlSessionFactory factory = null;
/**
* sqlSessionFactoryBuilder:唯一的作用就是创建sqlSessionFactory
* 一旦用完就可以把它把抛弃了
* 1.类加载的时候就会执行
* 2.只会执行一次
*/
static {
try {
factory = new sqlSessionFactoryBuilder().build(
Resources.getResourceAsReader("mybatis-config.xml")
);
} catch (Exception e) {
e.printstacktrace();
}
}
public static sqlSession openSession(){
return factory.openSession();
}
}
3.1 完成CRUD
3.1.1 productMapper.xml
<!--
select:代表这是一个查询语句
id:代表这个查询语句的唯一命名
以后你要找到这条sql: namespace+id
例:cn.itsource.dao.ProductMapper.getone
parameterType:参数类型
long -> Long _long -> long
resultType:返回的每一条结果的类型
注:返回类型的全限定名
-->
<select id="getone" parameterType="long" resultType="product">
select * from product where id = #{id}
</select>
<!--resultType:返回的每一条结果的类型-->
<select id="getAll" resultType="product" >
select * from product
</select>
<!--
添加一条数据
useGeneratedKeys:是否要主键
keyColumn="id":在数据库中名称叫id
keyProperty="id":在类中也叫id
主键会放到你传过来的对象中
-->
<insert id="save" parameterType="product"
useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into product
(productName,dir_id,salePrice,supplier,brand,cutoff,costPrice) values
(#{productName},#{dir_id},#{salePrice},#{supplier},#{brand},#{cutoff},#{costPrice})
</insert>
<!--修改功能-->
<update id="update" parameterType="product">
update product set
productName=#{productName},
dir_id=#{dir_id},
salePrice=#{salePrice},
supplier=#{supplier},
brand=#{brand},
cutoff=#{cutoff},
costPrice=#{costPrice}
where id=#{id}
</update>
<!-- 删除功能 -->
<delete id="delete" parameterType="long">
delete from product where id=#{id}
</delete>
3.1.1 productDao中完成功能
- 增删改需要提交事务
package cn.itsource.dao.impl;
import cn.itsource.dao.IProductDao;
import cn.itsource.domain.Product;
import cn.itsource.util.MyBatisUtil;
import org.apache.ibatis.session.sqlSession;
import java.util.List;
public class ProductDaoImpl implements IProductDao {
private final String NAMESPACE = "cn.itsource.dao.ProductMapper.";
@Override
public void save(Product product) {
sqlSession session = null;
try {
session = MyBatisUtil.openSession();
session.insert(NAMESPACE+"save",product);
//提交事务
session.commit();
} catch (Exception e) {
//回滚事务
session.rollback();
e.printstacktrace();
} finally {
session.close();
}
}
@Override
public void update(Product product) {
sqlSession session = null;
try {
session = MyBatisUtil.openSession();
session.update(NAMESPACE+"update",product);
//提交事务
session.commit();
} catch (Exception e) {
//回滚事务
session.rollback();
e.printstacktrace();
} finally {
session.close();
}
}
@Override
public void delete(Long id) {
sqlSession session = null;
try {
session = MyBatisUtil.openSession();
session.delete(NAMESPACE+"delete",id);
//提交事务
session.commit();
} catch (Exception e) {
//回滚事务
session.rollback();
e.printstacktrace();
} finally {
session.close();
}
}
@Override
public Product getone(Long id) {
sqlSession session = null;
try {
session = MyBatisUtil.openSession();
return session.selectOne(NAMESPACE+"getone",id);
} catch (Exception e) {
e.printstacktrace();
} finally {
session.close();
}
return null;
}
@Override
public List<Product> getAll() {
sqlSession session = null;
try {
session = MyBatisUtil.openSession();
return session.selectList(NAMESPACE+"getAll");
} catch (Exception e) {
e.printstacktrace();
} finally {
session.close();
}
return null;
}
}
四.细节处理
4.1 添加的对象返回id
<!--
添加一条数据
-->
<insert id="save" parameterType="product"
useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into product
(productName,dir_id,salePrice,supplier,brand,cutoff,costPrice) values
(#{productName},#{dir_id},#{salePrice},#{supplier},#{brand},#{cutoff},#{costPrice})
</insert>
4.2 别名的配置
- 内置别名(int,long,..)/自定义别名(自己的类)
- 别名不区分大小写
- 自定义别名的配置
- 每个对象单独配置别名
<typeAlias type="cn.itsource.domain.Product" alias="Product" />
- 扫描包(这个包的对象都会取别名)
<package name="cn.itsource.domain" />
- 每个对象单独配置别名
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- configuration:配置(xml的一个根)-->
<configuration>
<!--引入jdbc.propeties文件-->
<properties resource="jdbc.properties" />
<!--
typeAliases:配置别名
注:别名不区别大小写
-->
<typeAliases>
<!-- type:类型 alias:别名-->
<!--<typeAlias type="cn.itsource.domain.Product" alias="Product" />-->
<!--为这个包下面的所有类取别名(就是类名)-->
<package name="cn.itsource.domain" />
<package name="cn.itsource.query" />
</typeAliases>
<environments default="development">
...
</environments>
<mappers>
...
</mappers>
</configuration>
4.3 日志的处理
# ERROR错误的日志 WARN:警告 INFO:普通信息 DEBUG:调试日志 TRACE:日志
log4j.rootLogger=ERROR, stdout
#log4j.rootLogger=NONE
#把左边包名改成你自己的包名
log4j.logger.cn.itsource=TRACE
# 日志打印到控制台中
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
# 日志打印的一种格式(可以灵活地指定布局模式)
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# 日志打印的格式是什么样子的 %d:日期 %p:优先级 %c:类的全名 %m:输出的结果 %n:换行
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
4.4 #与$的区别(面试题)
五.批量操作与动态sql
5.1 批量添加
- sql:
insert into 表名 (列名,列名) values (?,?),(?,?),...
- 实现使用foreach
<!--
批量添加
insert into employee (name,age,sex) values
("小小良",45,false),("大二良",45,true)
foreach:循环
collection:遍历的集合
item:每次遍历拿到的对象
separator:分隔符(每个值都使用,隔开)
-->
<insert id="batchSave" parameterType="list">
insert into employee (name,age,sex) values
<foreach collection="list" item="e" separator=",">
(#{e.name},#{e.age},#{e.sex})
</foreach>
</insert>
5.2 批量删除
- sql:
delete from 表名 where id in(?,?,..)
- 实现使用foreach
<!--
批量删除:DELETE FROM employee WHERE id in (?,?,?,...)
传 : List<Long> ids
foreach:循环
collection:遍历的集合
item:每次遍历拿到的对象
separator:分隔符(每个值都使用,隔开)
open:以什么开头
close:以什么结尾
index:遍历的索引
-->
<delete id="batchDelete" parameterType="list">
delete from employee where id in
<foreach collection="list" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
5.3 动态修改
<!--
动态修改:只修改有值的数据
-->
<update id="dynamicUpdate" parameterType="employee">
update employee
<set>
<if test="name!=null">
name=#{name},
</if>
<if test="age!=null">
age=#{age},
</if>
<if test="sex!=null">
sex=#{sex},
</if>
</set>
where id=#{id}
</update>
今日扩展
连接池
比较流行的连接池有三个
- Spring建议使用的DBCP
- Hibernate建议使用的C3P0
- 阿里连接池 druid -> 现在外面用得还是比较多