mybatis一些问题的总结

mybatis一些总结

mybatis使用注解开发和xml区别

mybatis之所以优先使用xml编写sql代码主要是当修改sql的时候代码不用重新编译,解耦性更好。

mybatis中${} 和 #{}区别

  1. ${}会直接对sql进行字符串拼接,在特殊情况下使用#{}会出现问题

    select * from #{table_name}
    //table_name = "test",解析后
    select * from "test"
    //使用${table_name},解析后
    select * from test
    

    使用#{}

    image-20210413091420572

    使用${}, 直接进行字符串的拼接image-20210413091700135

  2. #{}是可以防止sql注入的,预处理阶段使用?代替,真正查询的时候才传入参数,类似于jdbc中的PreparedStatement。

总结: 在传入表名,字段名的时候直接使用${},其他的时候就使用#{}

动态标签总结

  1. if test返回true的时候把if中的sql片段拼接进入sql语句。

  2. choose when otherwise 可以实现类似于 if...else 的功能

  3. where 当where标签包含的元素有返回值的时候在sql中加where,where 后面字符串以and or开头就去掉

  4. update语句中的 set 标签 ,set标签包含的元素有返回值的时候在sql中加set , set 后面的字符串以,结尾就去掉

  5. where标签和set标签是trim的特殊情况,也就是说可以使用trim来实现where和set标签,trim标签的属性如下:

    1. prefix:当trim元素内包含内容时,会给内容增加 prefix指定的前缀。
    2. prefixOverrides:当trim元素内包含内容时,会把内容中匹配的前缓字符串去掉。
    3. suffix:当trim元素内包含内容时,会给内容增加 suffix指定的后缀。
    4. suffixOverrides:当trim元素内包含内容时,会把内容中匹配的后缀字符串去掉。
  6. foreach 标签用来循环拼接,可以实现sql中的实现in ,批量插入等

    1. 在Map中key 是存储在map中的key值,在实现Iterable的类中key是索引值index
  7. bind 标签可以创建一个变量,用于字符串拼接或者打印其他变量的值等。

  8. OGNL 支持逻辑运算与,非,大于,小于等,可以使用类的静态方法,对象的方法和字段。if when的 test bind 的 value属性都支持OGNL

一对一总结

  1. 直接在sql语句中使用as进行把关联对象的属性和查询出来的字段对应起来

  2. 使用resultMap的result标签把关联对象的属性和查询出来的字段对应起来

  3. 使用resultMap标签中的 association 标签,指定一个resultMap,把关联对象的属性和查询出来的字段对应起来

    此时association标签常用的属性

    1. property 对象里面关联对象的属性名
    2. resultMap 指定关联对象对应的resultMap
    3. columnPrefix:就是对于的ResultMap配置好的colum中都加入这个前缀,那么在sql语句中要对应的也要加入这个前缀

    前三种方法都是使用一次sql查询就查询出结果,这样导致的问题就是sql编写复杂,容易出错。

  4. 使用resultMap标签中的 association 实现嵌套查询实现一对一查询。也就是执行多次sql完成查询。

    此时association的常用属性如下

    1. property
    2. column 列名(或别名),将主查询中列的结果作为嵌套查询的参数,配置方式如column={ prop1=col1,prop2=co12},prop1和prop2将作为嵌套查询的参数。这边的prop1要和接下来执行的sql参数名一致,col1要和查询出来的列名一致。
    3. select 值是对应的select标签的id,mybatis会执行这个select得到嵌套对象
    4. 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 标签实现一对多查询

  1. 第一种还是不嵌套的方式,也就是执行一次sql 获取结果

    collection 标签的常用属性

    1. property
    2. resultMap
    3. 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"
    
  2. 第二种是嵌套查询

    collection 标签的常用属性

    1. property
    2. select
    3. column
posted @ 2021-04-14 20:58  ${yogurt}  阅读(142)  评论(0编辑  收藏  举报