MyBatis延迟加载、缓存机制与注解开发

一、延迟加载策略

1.1 延迟加载的概念

立即加载:查询用户时,默认也把该用户的所有账户信息查询出来

延迟加载:查询用户时,不查询账户信息,等需要使用账户数据时才去查询

1.2 应用场景

查询账户(多对一)时,可以直接查询用户信息 → 立即加载

查询用户(一对多)时,可以先不查账户信息 → 延迟加载

1.3 多对一延迟加载配置

在 SqlMapConfig.xml 中开启延迟加载:

复制代码
<settings>
    <!-- 开启延迟加载 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 将积极加载改为按需加载 -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

AccountMapper.xml 配置:

复制代码
<resultMap id="accountMap" type="Account">
    <result property="id" column="id"/>
    <result property="uid" column="uid"/>
    <result property="money" column="money"/>
    <association property="user" javaType="User" 
                 select="com.qcbyjy.mapper.UserMapper.findById" 
                 column="uid"/>
</resultMap>

<select id="findAll" resultMap="accountMap">
    SELECT * from account
</select>

二、MyBatis缓存机制

2.1 一级缓存(SqlSession缓存)

一级缓存是 SqlSession 级别的缓存,底层使用Map集合存储:

key:执行的SQL语句

value:查询的结果对象

一级缓存的生命周期与SqlSession相同。以下操作会清空一级缓存:

session.clearCache()

session.update()、insert()、delete()、commit()、close()

复制代码
@Test
public void testFindById() {
    User user = mapper.findById(41);
    System.out.println(user);
    // 第二次查询会从缓存中获取,不会查询数据库
    User user2 = mapper.findById(41);
    System.out.println(user2);
}

三、注解开发

3.1 单表CRUD注解

在 SqlMapConfig.xml 中配置Mapper接口所在的包:

复制代码
<mappers>
    <package name="com.qcbyjy.mapper"/>
</mappers>

UserMapper接口:

复制代码
public interface UserMapper {
    
    @Select("select * from user")
    @Results(id="userMap", value={
        @Result(id=true, column="id", property="id"),
        @Result(column="username", property="username"),
        @Result(column="birthday", property="birthday"),
        @Result(column="sex", property="sex"),
        @Result(column="address", property="address")
    })
    public List<User> findAll();
    
    @Select("select * from user where id = #{uid}")
    @ResultMap("userMap")
    public User findById(Integer uid);
    
    @Insert("insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})")
    public void insert(User user);
    
    @Update("update user set username = #{username},birthday=#{birthday},sex=#{sex},address=#{address} where id = #{id}")
    public void update(User user);
    
    @Delete("delete from user where id = #{id}")
    public void delete(Integer userId);
    
    @Select("select count(*) from user")
    public Integer findByCount();
    
    @Select("select * from user where username like #{username}")
    public List<User> findByUsername(String username);
}

3.2 多对一注解查询(延迟加载)

复制代码
public interface AccountMapper {
    
    @Select("select * from account")
    @Results(value={
        @Result(id=true, column="aid", property="id"),
        @Result(column="uid", property="uid"),
        @Result(column="money", property="money"),
        @Result(property="user", javaType=User.class, column="uid",
                one=@One(select="com.qcbyjy.mapper.UserMapper.findById", 
                         fetchType=FetchType.LAZY))
    })
    public List<Account> findAll();
}

3.3 一对多注解查询(延迟加载)

复制代码
public interface UserMapper {
    
    @Select("select * from user")
    @Results(id="userMap", value={
        @Result(id=true, column="id", property="id"),
        @Result(column="username", property="username"),
        @Result(column="birthday", property="birthday"),
        @Result(column="sex", property="sex"),
        @Result(column="address", property="address"),
        @Result(property="accounts", column="id",
                many=@Many(select="com.qcbyjy.mapper.AccountMapper.findByUid", 
                          fetchType=FetchType.LAZY))
    })
    public List<User> findAll();
}

public interface AccountMapper {
    @Select("select * from account where uid = #{uid}")
    public List<Account> findByUid(Integer uid);
}

四、总结

|-------|-------------|---------------------|
| 特性 | XML方式 | 注解方式 |
| 简单语句 | 支持 | 支持,更简洁 |
| 复杂语句 | 支持 | 较复杂 |
| 动态SQL | 支持良好 | 支持但较繁琐 |
| 可读性 | 较高 | 高(简单语句) |
| 推荐场景 | 复杂SQL、动态SQL | 简单SQL、Spring Boot项目 |

实际开发建议:简单SQL可以使用注解方式,复杂SQL和动态SQL建议使用XML方式-。

相关推荐
念何架构之路3 小时前
Go reflect 包:结构体反射 —Field、Tag 与 VisibleFields
java·数据库·golang
liangbo74 小时前
03-JDK 10/11 局部变量推断与 LTS:var 到底该怎么用
java
Percep_gan4 小时前
调用天翼云的对象存储ZOS,很详细
java·1024程序员节
若亦_4 小时前
数据结构>>优先级队列(堆)
java·数据结构
Wang's Blog5 小时前
Java 项目实战: 交友项目 - 查询圈子个人动态:查询我的动态需求分析
java·开发语言·交友
denlaku5 小时前
JDK 23 新特性详解
java
code2cat5 小时前
Java高级篇之Hibernate:让对象映射到表,理解持久化与事务
java·后端·hibernate·1024程序员节
骑着蜗牛撵大象3275 小时前
飞牛fnOS部署Damselfly:Compose编排、照片目录与7100固定访问
java·docker·rpc·dubbo·fnos·照片管理·damselfly
金銀銅鐵6 小时前
[Java] 用 CLI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
Nuanyt6 小时前
Hot 100 刷题笔记 · 数组与哈希专题(3 题)
java·笔记·算法·leetcode·哈希算法·1024程序员节