框架系列——MyBatis

MyBatis

MyBatis 与 Hibernate 有哪些不同?

Mybatis 相对于 Hibernate 称为半 ORM 框架,因为 Hibernate 不需要写 SQL,而 Mybatis 需要写 SQL。
也因为这点 Mybatis 更加的灵活且轻量。
能针对 SQL进行优化,非常灵活地根据条件动态拼接 SQL等,极端情况下性能占优。

--#{} 和 ${} 的区别

--#{} 完全相当于jdbc中的 ? 占位符,底层在处理的时候,就是按 ?处理的 (用 PreparedStatement 的 setObject() 方法 )
如果用 #{} 这样的方式,当参数是简单类型的时候{} 里的内容名称随意

${} 它就是当作变量值直接拼接
如果用 ${} 的方式,则{} 中间的值,通常写成 ${value}

为什么避免使用二级缓存 ?

​ 在符合【Cache使用时的注意事项】的要求时,并没有什么危害。

​ 其他情况就会有很多危害了。
​ 1)针对一个表的某些操作不在他独立的namespace下进行。
例如在UserMapper.xml中有大多数针对user表的操作。但是在一个XXXMapper.xml中,还有针对user单表的操作。
这会导致user在两个命名空间下的数据不一致。如果在UserMapper.xml中做了刷新缓存的操作,
在XXXMapper.xml中缓存仍然有效,如果有针对user的单表查询,使用缓存的结果可能会不正确。

​ 2)更危险的情况是在XXXMapper.xml做了insert,update,delete操作时,会导致UserMapper.xml中的各种操作充满未知和风险。
​ 有关这样单表的操作可能不常见。但是你也许想到了一种常见的情况。

​ 多表操作一定不能使用缓存 为什么不能?

​ 首先不管多表操作写到那个namespace下,都会存在某个表不在这个namespace下的情况。

​ 例如两个表:role和user_role,如果我想查询出某个用户的全部角色role,就一定会涉及到多表的操作。

		<select id="selectUserRoles" resultType="UserRoleVO">
		    select * from user_role a,role b where a.roleid = b.roleid and a.userid = #{userid}
		</select>

​ 像上面这个查询,你会写到那个xml中呢??

​ 不管是写到RoleMapper.xml还是UserRoleMapper.xml,或者是一个独立的XxxMapper.xml中。如果使用了二级缓存,都会导致上面这个查询结果可能不正确。

​ 如果你正好修改了这个用户的角色,上面这个查询使用缓存的时候结果就是错的。

​ 这点应该很容易理解。

​ 在我看来,就以MyBatis目前的缓存方式来看是无解的。多表操作根本不能缓存。

​ 如果你让他们都使用同一个namespace(通过)来避免脏数据,那就失去了缓存的意义。

Mybatis 中有两类缓存,分别是一级缓存和二级缓存:
级缓存默认开启,二级缓存默认关闭,若开启可在 SqlSession 之间共享缓存数据。级缓存默认是会话级缓存。即创建一个Salsession对象就是一个会话,一次会话可能会执行多次相同的查询,这样缓存了之后就能重复利用查询结果,提高性能,不过 commit、rollback、update、delete 等都会清除缓存。不过要注意,不同 SalSession之间的修改不会影响彼此,比如 Salsesion1 读了数据A,SalSession2将数据改为 B,此时 SalSession1 再读还是得到 A这就出现了脏数据的问题。
所以,如果是多 SqlSession 或者分布式环境下,就可能有脏数据的情况发生,建议将一级缓存级别设置为 statement,_级缓存是跨 SqlSession 级别的共享的,同一个 namespace 下的所有操作语句,都影响着同一个 Cache。

开启二级缓存之后,会先从二级缓存查找,找不到再去一级缓存查找,如果一级缓存没有再去数据库查询。

在分布式场景下肯定会出现脏数据建议生产上使用 redis 结合 spring cache 进行数据的缓存,或者利用 guava、caffeine 进行本地缓存。

posted @ 2024-07-31 01:51  AbjLink  阅读(3)  评论(0编辑  收藏  举报