用了很久的Mybatis,但是一直没有全面去学过,这次补一下基础吧
Mybatis
当使用Mybatis时,首先用字节流通过Resource将配置文件读入,然后通过SqlSessionFactoryBuilder().build方法创建SqlSessionFactory,然后再通过sqlSessionFactory.openSession()方法创建一个sqlSession。Mybatis通过xml文件映射到各实体类的Mapper接口,Mapper接口中配置了每个类对数据库所需进行的sql语句映射。
经历了Mybatis初始化 –>创建SqlSession –>运行SQL语句 返回结果三个过程
mybatis缓存概念
当我们使用Mybatis进行数据库的操作时候,MyBatis会开启一个会话时,然后创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象,Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。
一级缓存:(HashMap来实现,并没有对HashMap的容量和大小进行限制,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象)
对SqlSession的操作mybatis内部都是通过Executor来执行的,Executor在执行数据库查询的时候总是先查看缓存中是否存在,若不存在则查询数据库。
SqlSession是对外接口,Executor是内部执行器
二级缓存:
二级缓存的范围更大,根据namespace
划分的,多个SqlSession
可以共享一个UserMapper
的二级缓存区域。
每一个namespace
的mapper
有一个二级缓存区域。也就是说如果两个mapper
的namespace
相同,那么这两个mapper
执行sql
查询到的数据将存储在一个二级缓存区域中。
mybatis的二级缓存是通过CacheExecutor实现的。CacheExecutor其实是Executor的代理对象。所有的查询操作,在CacheExecutor中都会先匹配缓存中是否存在,不存在则查询数据库。二级缓存是可以跨SqlSession的
MyBatis查询数据的顺序是:
二级缓存 ———> 一级缓存——> 数据库
要使用Mybatis的二级缓存,需要对Mybatis进行配置,配置分三步
Mybatis全局配置中启用二级缓存配置
1
<setting name="cacheEnabled" value="true"/>
在对应的Mapper.xml中配置cache节点
1
2
3
4
5<mapper namespace="userMapper">
<cache />
<result ... />
<select ... />
</mapper>在对应的select查询节点中添加useCache=true
1
2
3<select id="findUserById" parameterType="int" resultMap="user" useCache="true">
select * from users where id=#{id};
</select>实体类要实现序列化接口
1
2
3
4public class User implements Serializable{
//属性......
//getter and setter......
}
区别
一级缓存是sqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap),用于存储缓存数据。不同的sqlSession之间的缓存区域(HashMap)是互不影响的。
二级缓存是mapper级别的缓存,多个sqlSession去操作同一个Mapper的sql语句,多个SqlSession可以公用二级缓存,二级缓存是跨sqlSession的。
MyBatis和Hibernate各有什么优缺点?
Hibernate
的优点是它是一个完全的ORM框架
,使用Hibernate
可以做到不用手写SQL,而且无须关心使用何种数据库,可移植性较好,当需要更变数据库时需要做的修改很少甚至为0。其缺点是需要根据数据库的设计在实体进行又一次的配置,且帮程序员做了太多事,如果需要进行调优的话需要对Hibernate
有比较深的了解。MyBatis
的优缺点差不多和Hibernate
相反,我们需要手写SQL
语句和配置结果集和实体类的映射
,即使是简单的单表操作也需要写SQL(可以通过拦截器
来实现CommonMapper,或者可以使用生成器来生成代码),因此MyBatis
要进行SQL调优也简单直接。其次是MyBatis
的二级缓存
功能较弱,是针对namespace
的。
动态SQL
TypeHandler
TypeHandler可以让数据库字段类型和Java类做一个映射,就好像默认text类可以转成String,但是可以用TypeHandler来转成Java自定义类型