转载

Mybatis使用陷阱

缓存不是基于行的

“缓存并不是基于行的”的意思就是,mybatis缓存的粒度是全部查询结果,而不是查询结果的每行,这也就意味着每次查询,就只有一份缓存,而不是有几行就有几分缓存。

这点和hibernate很不同,hibernate的缓存是基于每个对象的,即查询出来的有几个对象,那就有几份缓存。

mybatis无法像hibernate给每个对象做缓存,主要原因是mybatis非常自由,能够配置任意的返回结果类型,这也就是说返回的结果并不一定都有主键,如此一来也就没有办法标识某一行数据和哪个返回结果对应,而hibernate是强制你所映射的每个类都要有主键的。

参考文档: http://www.mybatis.org/mybatis-3/sqlmap-xml.html#cache

缓存默认没有失效时间

“缓存默认没有失效时间”的意思是如果我们直接在数据库里修改数据,那么每次用mybatis查询的时候,使用的还是上一次的缓存结果,且这份缓存一直有效,除非我们通过mapper调用了update、delete、insert方法,这些方法会使缓存失效。解决办法很简单,就是在使用 <cache /> 的时候一定要写上 flushInterval 属性。

参考文档: http://www.mybatis.org/mybatis-3/sqlmap-xml.html#cache

使用Partial Auto-mapping后,自动去重问题

Partial Auto-mapping的意思是你对ResultMap只提供了部分字段的配置而不是全部字段,但是如果你的这个ResultMap没有设置ID,也就是主键,那么mybatis将会根据你提供的这一部分字段配置来判断两行数据是否重复,并且会将重复的去掉。

实际上关于id的作用在官方文档中很隐晦的提到过了:见 http://www.mybatis.org/mybatis-3/sqlmap-xml.html#Result_Maps 的id & result部分。

比如下面这个配置启用了 autoMapping ,且部分配置了property的映射。在这种情况下,如果查询出两条记录了,而这两条记录的 task_key 的值是一样的时候,mybatis就会认为是同一条,最终返回给你一个 AuditLog

<resultMap id="AuditLog" type="AuditLog" autoMapping="true">    <result column="task_key" property="taskKey"/> </resultMap>

解决办法有两个:

  1. 不配置property的映射:

    <resultMap id="AuditLog" type="AuditLog" autoMapping="true"> </resultMap>
  2. 不使用automapping:

    <resultMap id="AuditLog" type="AuditLog">     <result column="task_key" property="taskKey"/>     <result column="result" property="result"/>     <result column="when" property="when"/>     <result column="name_zh" property="nameZh"/>     <result column="name_en" property="nameEn"/>     <result column="remark" property="remark"/> </resultMap>

参考文档: http://www.mybatis.org/mybatis-3/sqlmap-xml.html#Auto-mapping

aggressiveFetch的问题

在使用mybatis懒加载特性的时候有一点需要注意,就是要把 aggressiveFetch 设置为 false

根据官方文档,当设置为true的时候,如果你get了懒加载属性,那么其他懒加载属性也会一并加载。

但实际情况时,当设置了true的时候,如果你get了 任一 属性,那么 所有 懒加载属性也会一并加载。

原文  https://segmentfault.com/a/1190000005960205
正文到此结束
Loading...