Mybaits常见问题

1.mybatis中${} 和#{}有什么区别?

      #{}:底层会翻译占位符?,将来使用PreparedStatement执行编译sql。形参如果是简单类型,并且只有一个#{随便}

      ${}:底层是字符串替换,将来会使用PreparedStatement执行sql,可能会出现sql注入。形参如果是简单类型,并且只有一个¥{value};常用于动态表查询

2.mybatis如何执行批量插入?

  循环单次插入;

     使用SpringBoot项目直接循环插入

  MP批量插入功能:

     使用三层架构(controller,service,mapper)实现效率比循环单次效率高;

     MP插入的核心实现代码是saveBatch方法,调用executeBatch方法进行插入,其实现过程为将插入的数据分成N份,每满1000条就会执行一次批量插入,所以性能要比循环单次插入的性能高。

  原生批量插入功能:

      原生批量插入方法是依靠MyBatis中的foreach标签,将数据拼接成一条原生的insert语句一次执行,在XML文件中进行操作。

     缺点:使用原生方法进行SQL拼接时,若超过默认情况下可以执行的最大SQL(4M)时,程序就会报错。(也是为什么 MP 需要分批执行的原因)

     解决措施:可以通过设置可以执行的最大SQL来解决

              -- 设置最大执行 SQL 为 10M
               set global max_allowed_packet=10*1024*1024;

3.mybatis如何在插入后获得主键 ?

     第一种:在xml文件中,insert标签属性中,添加userGenatedKeys和KeyProperty

     第二种:在xml文件中添加selectKey标签属性,各个属性值含义:

             resiultType:查询结果的类型;

             keyProperty:把查询的值赋给谁;

             order:在插入前还是后执行,id在insert语句插入之后才会生成id,所以要在插入之后执                              行,所以此处order=after

     第三种:在dao层用注解的方式,用@SelectKey注解,里面属性含义:

            resultType:查询结果的类型

            keyProperty:把查询的值赋给谁;

            statement:查找最后一个插入的id;

            KeyColumn:查询的是哪一列

            before:是否在插入之前执行,id在insert语句插入之后才会生成id,所以要在插入之后执                                  行,所以此处before=false

     第四种:在对应的实体类种指定主键id的

  @TableId(type = IdType.ASSIGN_ID)
    private Long id;

4.mybatis中resultType和resultMap区别?

  • 对象不同

   resultMap:如查处的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名                         之间做一个映射关系

   resultType :使用resultType进行输出映射,只有查出的实体类和列名一致,该列才能映射成功

  • 描述不同

   resultMap:对于一对一表连接的处理方式通常在主表的pojo添加嵌套另一个表的pojo,然后在                          mapper.xml中采用associaton节点元素进行对另一个表的连接处理

   resultType :该字段无法查询结果结果映射到pojo对象的pojo属性中,根据对结构集查询遍历的                        需要选择使用resultType还是resultMap

  • 类型不适(二者不可同时使用)
  • mybatis中在查询进行select映射的时候,返回值类型二者都可用

      resultMap:resultMap是对外部resultMap的引用。

      resultType :resultType是直接表示返回类型的。

    5.mybatis一级缓存和二级缓存?

 一级缓存:
     概述:   

          一级缓存也叫本地会话,对于一个sqlSession,如想要多次执行同一条sql,第一次会把查询结果保存在一级缓存中,再次查询时会直接去一级缓存中获取,不会再次访问数据库,大大减少了数据库的负压,但是此时sqlSession关闭链接之后,一级缓存就会被清理。

      一级缓存之中的数据是基于hashmap存储的,是属于sqlSession级别的缓存,在sqlsession对象内部维护Map。

    执行流程

            当执行sql语句的时候,首先将sql语句和参数作为key,在一级缓存中查找数据,如果有数据:直接返回,如果没有,将sql语句发送到数据库中,数据库执行sql返回语句。将sql语句和参数作为key,将查询到的数据作为value存入一级缓存。

      每个sqlSession有自己的一级缓存。

   一级缓存的清理:

                     当执行增删改操作时,sqlSession一级缓存会被清理

                     当我们调用sqlSession。cleanCache()清理一级缓存

二级缓存:
   概述:

       也叫全局缓存,当sqlSession关闭连接后,会将一级缓存中的数据转存到二级缓存中。默认情况下时不开启的,但是如是要启用,需要在每个XML文件中添加以配置该级缓存(相应的实体类要序列化)

      sqlSessionFactory级别的缓存,可以被所有的sqlSession共享

执行流程:

      通过SqlSession查询数据时,这些数据将会放到当前的一级缓存中;如果当前会话关闭,则一级缓存中的数据会被保存到二级缓存中,此后新的sqlSession将会从二级缓存中查找数据;

二级缓存清理:

     select标签的useCache属性用于设置是否使用二级缓存,默认时true;

   

     

       增删改查标签均有flushCache属性,其中增删改默认true,即sql执行以后,会同时清空一级二级缓存,查询默认false。 

 总结:

       mybatis的一级缓存和二级缓存都是基于本地,分布式的环境下必然会出现脏。

       二级缓存可以通过实现Cache接口,来集中管理缓存,避免脏读,但是有一定的开发成本,并且在多表查询时,使用不当既有可能会出现脏读数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值