MyBatis
一、概述
1.1 MyBatis是什么
MyBatis是一款半自动的ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一、一对多),动态SQL,延迟加载和缓存等特性,但数据库无关性较低
ORM: 对象关系映射(在Java对象和数据库的关系模型之间建立一种对应关系)
半自动的ORM框架: 需要手动编写SQL语言,具有较高的灵活性,也因此切换数据库时,SQL语句可能就需要重写。但相较于JDBC,提供了输入映射和输出映射,设置SQL参数,结果封装、关联查询和动态SQL功能,提高了开发效率.
1.2 MyBatis与JPA的区别
- ORM映射不同
MyBatis是半自动的ORM框架,提供数据库与结果集的映射
JPA(默认采用Hibernate)是全自动的ORM框架,提供对象与数据库的映射 - 可移植性不同
JPA通过它强大的映射结构和HQL语言,降低了对象和数据库的耦合性
MyBatis由于需要些SQL语言,因此与数据库的耦合直接取决于SQL的写法,在使用了大量数据库方言时移植性降低 - 日志系统的完整性不同
JPA日志系统非常健全:SQL记录、关系异常、优化警告、缓存提示、脏数据警告等
MyBatis只有基本的记录功能。 - SQL优化上的区别
MyBatis的SQL都写在XML中,优化SQL比Hibernate方便很多
Hibernate的SQL很多是自动生成的,无法直接维护。虽然有HQL,但是功能弱很多,灵活性不如MyBatis。
二、MyBatis输入输出支持的类型
- 基本类型:整数、小数、字符串等
- 集合:Map等
- 自定义的JavaBean
基本类型直接映射到参数上,Map或者JavaBean将其属性按照名称映射到参数上
三、如何实现一对多关联查询
3.1 联合查询ResultMap映射
sql直接关联查询,结果集通过resultMap的collection映射,将【多】对应的字段映射上去
优点:条件查询方便;无论是订单表还是详情表如果要进行一些条件过滤的话,非常方便,直接写在where中限制就行。
缺点:因为是先关联查询,后映射;如果要进行分页查询就无法满足。主表2条,详情表5条,关联后10条,无法对主表进行分页——解决办法:献给主表套一个子查询limit分页后,结果集和详情表关联查询
3.2 子查询映射
通过resultMap中collection标签的select属性去执行子查询,所需参数通过column传递;
优点:无论是分页还是普通查询都能满足;主表增加过滤条件也很方便,直接在主查询的sql中增加where条件就行
缺点:子查询不好增加过滤条件,column只能传递主表已有的字段
四、MyBatis中的$和#
4.1 #{}
- 表示一个占位符,相当于jdbc中的
?
符号 - #{}将传入的数据都当成一个字符串,会对自动传入的数据加一个
双引号
。如 select * from user where id= #{user_id},如果传入的值是11,那么解析成sql时的值为where id=“11” - 如果sql语句中只有一个参数,此时参数名称可以随意定义。如果有多个参数,此时的参数名称应该是当前表关联【实体类的属性名】或者1【Map集合关键字】,不能随便写,必须对应
4.2 ${}
- 将传入的数据直接显示生成在sql中。如 select * from user where id= $ {user_id},如果传入的值是11,那么解析成sql时的值为where id=11
- v a l u e 中 v a l u e 值有限制只能写对应的 v a l u e 值不能随便写,因为 {value}中value值有限制只能写对应的value值不能随便写,因为 value中value值有限制只能写对应的value值不能随便写,因为{}不会自动进行jdbc类型转换
- 简单来说,在JDBC不支持使用占位符的地方,都可以使用${}
4.3 #{}和${}的区别
#{}方式能够很大程度防止sql注入(安全),${}方式无法防止Sql注入
在JDBC支持使用占位符的地方,最好使用#{}
在JDBC不支持使用占位符的地方,就只能使用${},典型情况就是动态参数
比如存在两种表table1和table2,如果在查询语句中需要动态指定表名,就只能使用 比如 M y B a t i s 排序时使用 o r d e r b y 动态参数时,也只能使用 {} 比如MyBatis排序时使用order by动态参数时,也只能使用 比如MyBatis排序时使用orderby动态参数时,也只能使用{}
五、MyBatis的xml文件和Mapper接口如何绑定
通过xml文件中 < mapper > 根标签的namespace属性绑定的,即nampespace属性的值需要配置成接口的全限定名称,MyBatis内部就会通过这个值将这个接口和这个xml关联起来
六 MyBatis的分页
MyBatis可以通过分页插件实现,也可以通过分页SQL自己实现分页。
分页插件的原理是拦截查询SQL,自动添加limit分页条件。但在分页偏移量很大的时候,效率较低,自己写的sql可以针对性优化
七、MyBatis缓存机制
MyBatis缓存分为一级缓存和二级缓存。
一级缓存:
又称为本地缓存,默认启用且不能关闭。一级缓存存在于SqlSession的生命周期中,即为SqlSession级别的缓存。在同一个SqlSession中查询时,MyBatis会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个Map对象中。如果同一个SqlSession中执行的方法和参数完全一致,那么会生成相同的键值,Map缓存对象中已经存在该键值时,会返回缓存中的对象。
二级缓存:
- 存在于SqlSessionFactory的生命周期中。若想使用二级缓存,需要在如下两处进行配置。
- 在MyBatis的全局配置settings中有一个参数cacheEnabled,这个参数是二级缓存的全局开关,默认是true,初始状态为启用状态。
- MyBatis的二级缓存是和命名空间绑定的,即二级缓存需要配置在Mapper.xml映射文件中。在保证二级缓存的全局配置开启的情况下,给Mapper.xml开启二级缓存只需要在Mapper.xml中添加如下代码:
<cache />
二级缓存具有如下效果:
- 映射语句文件中所有select语句会被缓存
- 映射语句文件中所有insert、update、delete语句会刷新缓存
- 缓存会使用LRU算法来收回
- 根据时间表,缓存不会以任何时间顺序来刷新
- 缓存会存储集合或对象的1024个引用
- 缓存会被视为可读/可写的,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不会干扰其他调用者或线程所做的潜在修改