Mybatis笔记
一、 mybatis框架
1.mybatis是什么?
mybatis是一个持久层框架,mybatis是一个不完全的ORM框架。sql语句需要程序员自己去编写,但是mybatis也有映射(输入参数映射、输出结果映射)。mybatis可以将向 preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射).Mybatis 只是对于 jdbc 的封装。
2.mybatis框架
3.mybatis框架执行过程:
(1)配置mybatis的配置文件,SqlMapConfig.xml(名称不固定)
(2)通过配置文件,加载mybatis运行环境,创建SqlSessionFactory会话工厂
SqlSessionFactory在实际使用时按单例方式。
(3)通过SqlSessionFactory创建SqlSession
SqlSession是一个面向用户接口(提供操作数据库方法),实现对象是线程不安全的,建议sqlSession应用场合在方法体内。
(4)调用sqlSession的方法去操作数据。
如果需要提交事务,需要执行SqlSession的commit()方法。
(5)释放资源,关闭SqlSession
二、Dao开发方法
2.1 原始Dao开发方法
(1)映射文件
(2)Dao接口
(3)Dao接口实现类
Public class UserDaoImpl implements UserDao {
//注入SqlSessionFactory
public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
this.setSqlSessionFactory(sqlSessionFactory);
}
private SqlSessionFactory sqlSessionFactory;
@Override
public User getUserById(int id) throws Exception {
SqlSession session = sqlSessionFactory.openSession();
User user = null;
try {
//通过sqlsession调用selectOne方法获取一条结果集
//参数1:指定定义的statement的id,参数2:指定向statement中传递的参数
user = session.selectOne("test.findUserById", 1);
System.out.println(user);
} finally{
session.close();
}
return user;
}
@Override
Public void insertUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
sqlSession.insert("insertUser", user);
sqlSession.commit();
} finally{
session.close();
}
}
}
(4)问题
原始Dao开发中存在以下问题:
******Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法
******调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不得于开发维护
2.2 Mapper接口开发方法(Mapper动态代理方式)
(1)实现原理
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper接口开发需要遵循以下规范:
【1】 Mapper.xml文件中的namespace与mapper接口的类路径相同。
【2】 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
【3】 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
【4】Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
(2)Mapper.xml映射文件
(3)接口文件
(4)加载Mapper.xml文件
<!-- 加载映射文件 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
(5)测试
InputStream is = Resources.getResourceAsStream("mybatis/SqlMapConfig.xml");
//通过配置文件SqlMapConfig.xml,创建SqlSessionFactory对象,然后产生SqlSession,执行SQL语句
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取代理对象
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = userDao.selectById(1);
System.out.println(user);
//关闭session
sqlSession.close();
三、XML配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
<configuration>
<!-- 加载类路径下的属性文件 -->
<properties resource="jdbc.properties"/>
<!-- settings -->
<settings>
<!-- 打开延迟加载的开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载(即按需加载) -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 打开全局缓存开关(二级缓存)默认值就是 true -->
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 设置类型别名 -->
<typeAliases>
<typeAlias type="ljh.entity.User" alias="user"/>
</typeAliases>
<!-- 和spring整合后 environments配置将废除-->
<!-- 设置一个默认的连接环境信息 -->
<environments default="mysql">
<!-- 连接环境信息,取一个任意唯一的名字 -->
<environment id="mysql">
<!-- mybatis使用jdbc事务管理方式 -->
<transactionManager type="JDBC"/>
<!-- 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>
<mapper resource="mybatis/mapper/UserMapper.xml"/>
</mappers>
</configuration>
SqlMapConfig.xml是mybatis核心配置文件,上边文件的配置内容为数据源、事务管理。
3.1配置内容
SqlMapConfig.xml中配置的内容和顺序如下:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
3.2配置详讲
(1)类型别名(typeAliases)
类型别名是为 Java 类型设置一个短的名字。 它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
(2)环境配置(environments)
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
(3)事务管理器(transactionManager)
(4)数据源(dataSource)
(5)映射器(mappers)
告诉 MyBatis 到哪里去找映射文件
*******<mapper resource=" " />使用相对于类路径的资源
*******<mapper url=" " />使用完全限定路径
*******<mapper class=" " />使用mapper接口类路径 注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
*******<package name=""/>注册指定包下的所有mapper接口 注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
四、XML映射文件
1、namespace等于mapper接口地址
2、输入映射(输入类型)
通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo,pojo的包装类型
3、输出映射(输出类型)
(1)resultType
******使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
******如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。
******只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。不一致的属性值为null。
******输出单个pojo对象,方法返回值是单个对象类型
******输出pojo对象list,方法返回值是List<Pojo>
******如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身
(2)resultMap
mybatis中使用resultMap完成高级输出结果映射。一致![](data:image/png;base64,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)
4、动态sql
(1)If
<select id="findUserList" parameterType="user" resultType="user">
select * from user
where 1=1
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</select>
注意要做不等于空和空字符串校验。
(2)where
<select id="findUserList" parameterType="user" resultType="user">
select * from user
<where>
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</where>
</select>
<where />可以自动处理第一个and。
(3) foreach
向sql传递数组或List,mybatis使用foreach解析
* 需求:传入多个id查询用户信息,用下边两个sql实现:
SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)
SELECT * FROM USERS WHERE username LIKE '%张%' id IN (10,89,16)
WHERE id=1 OR id=10 OR id=16
在查询条件中,查询条件定义成一个sql片段,需要修改sql片段。
(4) sql片段
需求:将上边实现的动态sql判断代码块抽取出来,组成一个sql片段。其它的statement中就可以引用sql片段。方便程序员进行开发。
定义sql片段
引用sql片段
在mapper.xml中定义的statement中引用sql片段:
五、延迟加载
需要查询关联信息时,使用mybatis延迟加载特性可有效的减少数据库压力,首次查询只查询主要信息,关联信息等用户获取时再加载。【用的时候加载不用的时候不加载】
在mybatis核心配置文件中配置:
lazyLoadingEnabled、aggressiveLazyLoading
设置项
|
描述
|
允许值
|
默认值
|
lazyLoadingEnabled
|
全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。
|
true | false
|
false
|
aggressiveLazyLoading
|
当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。
|
true | false
|
true
|
在mybatis核心配置文件中配置
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
六、Mybatis连接池和事务
1、连接池
(1)mybatis连接池分类
可以看出 Mybatis 将它自己的数据源分为三类:
UNPOOLED 不使用连接池的数据源
POOLED 使用连接池的数据源(最常用)
JNDI 使用 JNDI 实现的数据源
(2)Mybatis中数据源的配置
MyBatis 在初始化时,解析此文件,根据的 type 属性来创建相应类型的的数据源DataSource,即:type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例
type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
(3)Mybatis 中连接的获取过程分析
当我们需要创建 SqlSession 对象并需要执行 SQL 语句时,这时候 MyBatis 才会去调用 dataSource 对象
来创建 java.sql.Connection 对象。也就是说,java.sql.Connection 对象的创建一直延迟到执行 SQL 语句
的时候。
数据库连接是我们最为宝贵的资源,只有在要用到的时候,才去获取并打开连接,当我们用完了就再立即将数据库连接归还到连接池中。
2、Mybatis的事务控制
(1)JDBC中事务的控制在 JDBC 中我们可以通过手动方式将事务的提交改为手动方式,通过 setAutoCommit()方法就可以调整。
Mybatis 框架因为是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC
的 setAutoCommit()方法来设置事务提交方式的
SqlSession sqlSession = sqlSessionFactory.openSession(true);//手动将他的事务提交方式改为自动提交
掌握 Mybatis连接池技术、事务、复杂参数的传入、复杂结果集的封装,多表的关联查询。
七、查询缓存
1.SqlSessionFactoryBuilder、SqlSessionFacoty、SqlSession
sqlSessionFactory是mybatis中的一个中要的对象,通俗讲它是用来创建sqlSession对象的,而sqlSession用来操作数据库的。
(1)SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。
(2)SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。
(3)SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作,默认使用DefaultSqlSession实现类。
执行过程如下:
1. 加载数据源等配置信息
Environment environment = configuration.getEnvironment();
2. 创建数据库链接
3. 创建事务对象
4. 创建Executor,SqlSession所有操作都是通过Executor完成,mybatis源码如下:
5. SqlSession的实现类即DefaultSqlSession,此对象中对操作数据库实质上用的是Executor
结论:
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭。如下:
SqlSession session = sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
2.Mybatis缓存介绍
(1)mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。mybaits提供一级缓存,和二级缓存。
如下图,是mybatis一级缓存和二级缓存的区别图解:
Mybatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。Mybatis默认开启一级缓存。
Mybatis二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存。二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
3.一级缓存
第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。
如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
4.二级缓存
mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。
在核心配置文件SqlMapConfig.xml中加入
<setting name="cacheEnabled" value="true"/>
刷新缓存(就是清空缓存)
在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。
设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。
如下:
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">
总结:一般下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。
八、 mybatis逆向
1、什么是逆向工程
mybaits需要程序员自己编写sql语句,mybatis官方提供逆向工程 可以针对单表自动生成mybatis执行所需要的代码(mapper.java,mapper.xml、po..)
企业实际开发中,常用的逆向工程方式:
由于数据库的表生成java代码。
2、使用方法(会用)
运行逆向工程, 生成代码配置文件,执行生成程序, 使用生成的代码