1、Mybatis加载策略

1.1、什么是延迟加载

延迟加载:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载。

1.1.1、延迟加载的优点

先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快

1.1.2、延迟加载的缺点

因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。

1.1.3、注意事项

  • 在多表中,一对多,多对多:通常情况下采用延迟加载,一对一(多对一):通常情况下采用立即加载
  • 延迟加载是基于嵌套查询来实现的

1.2、延迟加载的实现

1.2.1、局部延迟加载

在association和collection标签中都有一个fetchType属性,通过修改它的值,可以修改局部的加载策略。

<!-- 开启一对多 延迟加载 -->
<resultMap id="userMap" type="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<!--
fetchType="lazy" 懒加载策略
fetchType="eager" 立即加载策略 -->

<collection property="orderList" ofType="order" column="id"
select="com.111.dao.OrderMapper.findByUid" fetchType="lazy">
</collection>
</resultMap>
<select id="findAll" resultMap="userMap">
SELECT * FROM `user`
</select>

1.2.2、设置触发延迟加载的方法

在配置文件中使用lazyLoadTriggerMethods配置项覆盖掉当前对象的equals、clone、hashCode、toString方法

<settings>
<!--开启全局延迟加载功能-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>

1.2.3、全局延迟加载

在Mybatis的核心配置文件中可以使用setting标签修改全局的加载策略。

<settings>

<!--开启全局延迟加载功能-->

<setting name="lazyLoadingEnabled" value="true"/>

</settings>

注意:

局部的加载策略优先级高于全局的加载策略。

1.3、Mybatis缓存

1.3.1、缓存的作用

经常查询一些不经常发生变化的数据,使用缓存来提高查询效率,通过缓存策略来减少数据库的查询次数,从而提高性能。

1.3.2、一级缓存

1.3.2.1、一级缓存的概述

一级缓存是SqlSession级别的缓存,是默认开启的

所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往 只执行一次SQL,因为使用SelSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时 候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不 会再次发送SQL到数据库

一文带你了解Mybatis的加载策略和常用注解_后端

1.3.2.2、验证一级缓存

@Test

public void testOneCache() throws Exception {

SqlSession sqlSession = MyBatisUtils.openSession();

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

User user1 = userMapper.findById(1); System.out.println("第一次查询的用户:" + user1);

User user2 = userMapper.findById(1); System.out.println("第二次查询的用户:" + user2);

sqlSession.close();

}

1.3.2.3、一级缓存的分析

一级缓存是SqlSession范围的缓存,执行SqlSession的C(增加)U(更新)D(删除)操作,或者调 用clearCache()、commit()、close()方法,都会清空缓存。

一文带你了解Mybatis的加载策略和常用注解_MyBatis_02

解释:

  1. 第一次发起查询用户id为41的用户信息,先去找缓存中是否有id为41的用户信息,如果没有,从数据库 查询用户信息。
  2. 得到用户信息,将用户信息存储到一级缓存中。
  3. 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这

样做的目的为了让缓存中存储的是最新的信息,避免脏读。

  1. 第二次发起查询用户id为41的用户信息,先去找缓存中是否有id为41的用户信息,缓存中有,直接从缓 存中获取用户信息。

1.3.2.4、清除一级缓存

@Test

public void testClearOneCache() throws Exception {

SqlSession sqlSession = MybatisUtils.openSession();

UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user1 = userMapper.findById(41); System.out.println("第一次查询的用户:" + user1);

//调用sqlSession清除缓存的方法 sqlSession.clearCache();

User user2 = userMapper.findById(41);

System.out.println("第二次查询的用户:" + user2); }
<!-- 每次查询时,都会清除缓存 -->

< select flushCache="true"></select>

1.3.3、二级缓存

1.3.3.1、二级缓存的概述

二级缓存是namspace级别(跨sqlSession)的缓存,是默认不开启的

二级缓存的开启需要进行配置,实现二级缓存的时候,MyBatis要求返回的POJO必须是可序列化的。 也就是要求实现Serializable接口,配置方法很简单,只需要在映射XML文件配置 就可以开启 二级缓存了。

一文带你了解Mybatis的加载策略和常用注解_MyBatis_03

1.3.3.2、验证

  • 配置核心配置文件
<settings>

<!-- 因为cacheEnabled的取值默认就为true,所以这一步可以省略不配置。 为true代表开启二级缓存;为false代表不开启二级缓存。

-->

<setting name="cacheEnabled" value="true"/>

</settings>
  • 配置UserMapper.xml映射
<mapper namespace="com.111.dao.UserMapper">
<!--当前映射文件开启二级缓存-->
<cache></cache>

<!--
<select>标签中设置useCache=”true”代表当前这个statement要使用二级缓存。 如果不使用二级缓存可以设置为false
注意:
针对每次查询都需要最新的数据sql,要设置成useCache="false",禁用二级缓存。
-->
<select id="findById" parameterType="int" resultType="user" useCache="true">
SELECT * FROM `user` where id = #{id}
</select>
</mapper>
  • 修改User实体类
public class User implements Serializable {
private Integer id;
private String username;

private Date birthday;

private String sex;

private String address;

private List<Role> roleList;

private List<Order> orderList;

}
  • 测试结果
@Test

public void testTwoCache() throws Exception {

SqlSession sqlSession = MyBatisUtils.openSession();

UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.findById(41); System.out.println("第一次查询的用户:" + user); sqlSession.close();

SqlSession sqlSession1 = MyBatisUtils.openSession();

UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class); User user1 = userMapper1.findById(41); System.out.println("第二次查询的用户:"+user1);

sqlSession1.close();
}

1.3.3.3、二级缓存的分析

二级缓存是mapper映射级别的缓存,多个SqlSession去操作同一个Mapper映射的sql语句,多个 SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

一文带你了解Mybatis的加载策略和常用注解_MyBatis_04

1. 映射语句文件中的所有select语句将会被缓存。

2. 映射语句文件中的所有insert、update和delete语句会刷新缓存。

1.3.3.4、注意事项

mybatis的二级缓存因为是namespace级别,所以在进行多表查询时会产生脏读问题

1.3.4、总结

  1. mybatis的缓存,都不需要我们手动存储和获取数据。mybatis自动维护的。
  2. mybatis开启了二级缓存后,那么查询顺序:二级缓存--》一级缓存--》数据库
  3. 注意:mybatis的二级缓存会存在脏读问题,需要使用第三方的缓存技术解决问题。

2、Mybatis常用注解

* @Insert:实现新增,代替了<insert></insert>

* @Delete:实现删除,代替了<delete></delete>

* @Update:实现更新,代替了<update></update>

* @Select:实现查询,代替了<select></select>

* @Result:实现结果集封装,代替了<result></result>

* @Results:可以与@Result 一起使用,封装多个结果集,代替了<resultMap></resultMap>

* @One:实现一对一结果集封装,代替了<association></association>

* @Many:实现一对多结果集封装,代替了<collection></collection>

注解延迟加载

* fetchType = FetchType.LAZY 表示懒加载

* fetchType = FetchType.EAGER 表示立即加载

* fetchType = FetchType.DEFAULT 表示使用全局配置