mybatis一些总结
mybatis使用注解开发和xml区别
mybatis之所以优先使用xml编写sql代码主要是当修改sql的时候代码不用重新编译,解耦性更好。
mybatis中${} 和 #{}区别
-
${}会直接对sql进行字符串拼接,在特殊情况下使用#{}会出现问题
select * from #{table_name} //table_name = "test",解析后 select * from "test" //使用${table_name},解析后 select * from test
使用#{}
使用${}, 直接进行字符串的拼接
-
#{}是可以防止sql注入的,预处理阶段使用?代替,真正查询的时候才传入参数,类似于jdbc中的PreparedStatement。
总结: 在传入表名,字段名的时候直接使用${},其他的时候就使用#{}
动态标签总结
-
if test返回true的时候把if中的sql片段拼接进入sql语句。
-
choose when otherwise 可以实现类似于 if...else 的功能
-
where 当where标签包含的元素有返回值的时候在sql中加where,where 后面字符串以and or开头就去掉
-
update语句中的 set 标签 ,set标签包含的元素有返回值的时候在sql中加set , set 后面的字符串以,结尾就去掉
-
where标签和set标签是trim的特殊情况,也就是说可以使用trim来实现where和set标签,trim标签的属性如下:
- prefix:当trim元素内包含内容时,会给内容增加 prefix指定的前缀。
- prefixOverrides:当trim元素内包含内容时,会把内容中匹配的前缓字符串去掉。
- suffix:当trim元素内包含内容时,会给内容增加 suffix指定的后缀。
- suffixOverrides:当trim元素内包含内容时,会把内容中匹配的后缀字符串去掉。
-
foreach 标签用来循环拼接,可以实现sql中的实现in ,批量插入等
- 在Map中key 是存储在map中的key值,在实现Iterable的类中key是索引值index
-
bind 标签可以创建一个变量,用于字符串拼接或者打印其他变量的值等。
-
OGNL 支持逻辑运算与,非,大于,小于等,可以使用类的静态方法,对象的方法和字段。if when的 test bind 的 value属性都支持OGNL
一对一总结
-
直接在sql语句中使用as进行把关联对象的属性和查询出来的字段对应起来
-
使用resultMap的result标签把关联对象的属性和查询出来的字段对应起来
-
使用resultMap标签中的 association 标签,指定一个resultMap,把关联对象的属性和查询出来的字段对应起来
此时association标签常用的属性
- property 对象里面关联对象的属性名
- resultMap 指定关联对象对应的resultMap
- columnPrefix:就是对于的ResultMap配置好的colum中都加入这个前缀,那么在sql语句中要对应的也要加入这个前缀
前三种方法都是使用一次sql查询就查询出结果,这样导致的问题就是sql编写复杂,容易出错。
-
使用resultMap标签中的 association 实现嵌套查询实现一对一查询。也就是执行多次sql完成查询。
此时association的常用属性如下
- property
- column 列名(或别名),将主查询中列的结果作为嵌套查询的参数,配置方式如column={ prop1=col1,prop2=co12},prop1和prop2将作为嵌套查询的参数。这边的prop1要和接下来执行的sql参数名一致,col1要和查询出来的列名一致。
- select 值是对应的select标签的id,mybatis会执行这个select得到嵌套对象
- fetchtype 数据加载方式,可选值为lazy和 eager,分别为延退加载和积极加载,这个配置会覆盖全局的lazyloadingenabled配置。
column 中使用column={ prop1=col1,prop2=co12} 这种格式对应的 select 标签中不能使用 parameterType 属性。使用 parameterType 属性会报错.
我的理解就是使用column={ prop1=col1,prop2=co12} 这个方式传送的可能不只一个参数,那么select标签中的parameterType 只能指定一个参数的类型,如果column中的参数不一致,这样就会发生错误。
<association property="teacher" column="{id=teacher_id}" select="com.example.mybatis_practice.yogurt.dao.TeacherMapper.selectByPrimaryKey" fetchType="lazy"/>
如果就使用标签 column=col1 传输一个参数 这种格式对应的 select 标签中能使用 parameterType 属性。
<association property="teacher" column="teacher_id" select="com.example.mybatis_practice.yogurt.dao.TeacherMapper.selectByPrimaryKey" fetchType="lazy" />
值得注意的是我们通常开启全局懒加载模式避免 N+1 问题,就是使用selectAll 返回N条数据,对每条数据都进行嵌套查询,一共要执行N次嵌套查询。还有就是生命周期的问题,sqlSession 会在控制层的时候被销毁,所以在控制层进行懒加载会出错。
在resultMap中,进行一对一和一对多 查询的时候,添加 id 子标签减少了字段的对比次数,有助于提高效率。如果没有添加id标签,他会对每一个result标签里column对应的字段进行比较。
**比较规则 : **
Mybatis会对每一层级的对象进行比较,Mybatis会对顶级对象进行比较,如果SysRole相同那么就比较SysRole对象,如果SysRole不同,就会添加一个SysRole,如果相同就会保留前一个SysRole。如果SysRole还有下一级就以此类推。
一对多总结
在resultMap中使用 collection 标签实现一对多查询
-
第一种还是不嵌套的方式,也就是执行一次sql 获取结果
collection 标签的常用属性
- property
- resultMap
- columnPrefix
值得注意的是columnPrefix是叠加的,也就是说columnPrefix中对应的resultMap中的association 或者 collection 又含有columnPrefix ,那么该resultMap中的column在sql中就要把两个Prefix全部加上
sp.id "role_privilege_id", sp.privilege_name "role_privilege_privilege_name", sp.privilege_url "role_privilege_privilege_url"
-
第二种是嵌套查询
collection 标签的常用属性
- property
- select
- column