当前位置: 首页 > news >正文

深入解析:MyBatis框架 - 延迟加载+一/二级缓存

目录

  • 一、延迟加载
    • 立即加载
    • 延迟加载
    • 实操案例
  • 二、缓存
    • 一级缓存
    • 二级缓存

一、延迟加载

立即加载

概念: 当查询主对象时,立即执行所关联的sql语句,一次性将对象数据全部查询出来。
行为: 执行SELECT * FROM order WHERE id = #{id}后,立马执行SELECT * FROM user WHERE id = #{userId}
使用场景: 多对一查询
优点: 数据一次性加载完毕,响应速度快。
缺点: 可能查询出不需要的数据,造成数据库资源和网络传输的浪费,降低性能。
使用: 默认使用立即加载。

延迟加载

概念: 当查询主对象时,只查询主对象的数据。关联对象的数据不会立即查询,只用程序第一次真正访问关联对象时,才会加载关联对象的数据。
行为: 先执行SELECT * FROM order WHERE id = #{id},当调用order.getUser()方法时,才执行SELECT * FROM user WHERE id = #{userId}

使用场景: 一对多查询
优点: 按需加载,避免了不必要的数据库查询。
缺点: 当第一次访问关联对象时,会有个短暂的查询延迟。后续访问多个关联对象,会产生多次数据库查询。
使用: 需要手动开启延迟加载。

  • 在主配置文件中开启延迟加载:lazyLoadingEnabledtrue开启延迟加载,aggressiveLazyLoading控制延迟加载的行为,默认值为false,按需加载
  • 在子配置文件中:在<association>标签或<collection>标签中设置fetchType指定哪个关联查询使用延迟加载。
    • fetchType属性值:lazy - 延迟加载;eager - 立即加载

实操案例

将一对多查询和多对一查询都进行延迟加载演示:
多对一延迟加载实操案例演示:

  • 在AccountMapper接口类中编写方法
    package com.tx.mapper;
    import com.tx.entity.Account;
    import java.util.List;
    public interface AccountMapper {
    // 延迟加载:多对一查询,查询某一个用户的所有账户信息
    public List<Account> findAccountAll();}
  • 在AccountMapper.xml中进行配置和SQL语句
    <mapper namespace="com.tx.mapper.AccountMapper"><!--延迟加载:多对一查询--><!--内连接查询--><select id="findAccountAll" resultMap="accountMap">select * from account</select><!--通过用户的id查询账户信息--><select id="findByUid" parameterType="int" resultType="account">select * from account where uid = #{uid}</select><!--配置映射--><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.tx.mapper.UserMapper.findUserById" column="uid" fetchType="lazy"><id property="id" column="id"/><result property="username" column="username" /><result property="birthday" column="birthday"/><result property="sex" column="sex"/><result property="address" column="address" /></association></resultMap></mapper>
  • 在UserMapper接口类中编写方法
    package com.tx.mapper;
    import com.tx.entity.User;
    import java.util.List;
    public interface UserMapper {
    // 延迟加载:多对一查询
    public List<User> findUserById(Integer uid);}
  • 在UserMapper.xml中进行配置文件
    <mapper namespace="com.tx.mapper.UserMapper"><!--配置延迟加载:多对一查询--><select id="findUserById" parameterType="int" resultType="user">select * from user where id = #{id}</select></mapper>
  • 在主配置文件中开启延迟加载
    <configuration><!--配置延迟加载--><settings><!-- 开启延迟加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- 将积极加载改为消极加载及按需加载 --><setting name="aggressiveLazyLoading" value="false"/></settings><!--定义类型别名--><typeAliases><package name="com.tx.entity" /></typeAliases><!--主配置文件--><!--配置环境们--><environments default="mysql"><!--配置环境--><environment id="mysql"><!--配置事务的类型,使用本地事务策略--><transactionManager type="JDBC"></transactionManager><!--配置是否使用连接池 POOLED表示使用链接池,UNPOOLED表示不使用连接池--><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql:///mybatis_db"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><!--加载映射文件--><mappers><mapper resource="mapper/UserMapper.xml"></mapper><mapper resource="mapper/AccountMapper.xml"></mapper></mappers></configuration>
  • 测试代码
    package com.tx.test;
    import com.tx.entity.Account;
    import com.tx.entity.User;
    import com.tx.mapper.AccountMapper;
    import com.tx.mapper.UserMapper1;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    // 入门程序
    public class Test01 {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    @Before
    public void init() throws IOException {
    // 1. 加载主配置文件,目的是构建SqlSessionFactory对象
    in = Resources.getResourceAsStream("SqlMapConfig.xml");
    // 2. 创建SqlSessionFactory(Sql会话工厂)对象
    factory = new SqlSessionFactoryBuilder().build(in);
    // 3. 获取session对象,使用SqlSessionFactory工厂对象创建SqlSession对象
    session = factory.openSession();
    }
    @After
    public void destory() throws IOException {
    // 5. 释放资源
    session.close();
    in.close();
    }
    // 4.1 延迟加载:多对一查询
    @Test
    public void testFindAccountAll(){
    // 4.1.1 通过session创建Mapper接口的代理对象
    AccountMapper mapper = session.getMapper(AccountMapper.class);
    // 4.1.2 执行方法
    List<Account> list = mapper.findAccountAll();for (Account account:list){System.out.println("开始……");System.out.println(account.getMoney());System.out.println(account.getUser().getUsername());System.out.println("结束……");System.out.println();}}}

结果
一对多延迟加载实操案例演示:

  • 在UserMapper接口类中编写方法
    package com.tx.mapper;
    import com.tx.entity.User;
    import java.util.List;
    public interface UserMapper1 {
    // 延迟加载:一对多查询
    public List<User> findUserAll();}
  • 在UserMapper.xml中进行配置和SQL语句
    <mapper namespace="com.tx.mapper.UserMapper1"><!--配置延迟加载:一对多查询--><select id="findUserAll" resultMap="userMap">select * from user</select><!--数据封装--><resultMap id="userMap" type="user"><id property="id" column=""/><result property="username" column="username"/><result property="birthday" column="birthday"/><result property="sex" column="sex"/><result property="address" column="address"/><!--select="":使用账号的方法查询column="":使用id值去查询账号--><collection property="accounts" ofType="account"select="com.tx.mapper.AccountMapper1.findAccountByUid" column="id" fetchType="lazy"><id property="id" column="id"/><result property="uid" column="uid"/><result property="money" column="money"/></collection></resultMap></mapper>
  • 在AccountMapper接口类中编写方法
    package com.tx.mapper;
    import com.tx.entity.Account;
    import java.util.List;
    public interface AccountMapper1 {
    // 延迟加载:一对多查询
    public List<Account> findAccountByUid(Integer uid);}
  • 在AccountMapper.xml中进行配置和SQL语句
    <mapper namespace="com.tx.mapper.AccountMapper1"><!--延迟加载:一对多查询--><!--通过用户的id查询账户信息--><select id="findAccountByUid" parameterType="int" resultType="account">select * from account where uid = #{uid}</select></mapper>
  • 在主配置文件中开启延迟加载
    <configuration><!--配置延迟加载--><settings><!-- 开启延迟加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- 将积极加载改为消极加载及按需加载 --><setting name="aggressiveLazyLoading" value="false"/></settings><!--定义类型别名--><typeAliases><package name="com.tx.entity" /></typeAliases><!--主配置文件--><!--配置环境们--><environments default="mysql"><!--配置环境--><environment id="mysql"><!--配置事务的类型,使用本地事务策略--><transactionManager type="JDBC"></transactionManager><!--配置是否使用连接池 POOLED表示使用链接池,UNPOOLED表示不使用连接池--><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql:///mybatis_db"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><!--加载映射文件--><mappers><mapper resource="mapper/UserMapper1.xml"></mapper><mapper resource="mapper/AccountMapper1.xml"></mapper><mapper resource="mapper/UserMapper2.xml"></mapper></mappers></configuration>
  • 测试代码
    // 4.2 延迟加载:一对多查询
    @Test
    public void testFindUserAll(){
    // 4.2.1 通过session创建Mapper接口的代理对象
    UserMapper1 mapper = session.getMapper(UserMapper1.class);
    // 4.2.2 执行方法
    List<User> list = mapper.findUserAll();for (User user:list){System.out.println("开始……");System.out.println(user.getUsername());System.out.println(user.getAccounts());System.out.println("结束……");System.out.println();}}

一级缓存

二、缓存

MySQL使用sql语句缓存。例如,select * from user和select *         from user,看起来时同一个表,但是,在MySQL缓存中,用第二表查询不到User表中的数据
MyBtais将数据进行缓存。

一级缓存

级别: SqlSession级别

实操案例:

  1. 在UserMapper2接口类中编写方法
    package com.tx.mapper;
    import com.tx.entity.User;
    public interface UserMapper2 {
    // 一/二级缓存
    public User findById(Integer id);
    }
  2. 在UserMapper2.xml中配置Sql语句
    <select id="findById" parameterType="int" resultType="user">select * from user where id = #{id}
    </select>
  3. 测试代码
    package com.tx.test;
    import com.tx.entity.User;
    import com.tx.mapper.UserMapper2;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import java.io.IOException;
    import java.io.InputStream;
    public class Test02 {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    @Before
    public void init() throws IOException {
    // 1. 加载主配置文件,目的是构建SqlSessionFactory对象
    in = Resources.getResourceAsStream("SqlMapConfig.xml");
    // 2. 创建SqlSessionFactory(Sql会话工厂)对象
    factory = new SqlSessionFactoryBuilder().build(in);
    // 3. 获取session对象,使用SqlSessionFactory工厂对象创建SqlSession对象
    session = factory.openSession();
    }
    @After
    public void destory() throws IOException {
    // 5. 释放资源
    session.close();
    in.close();
    }
    // 4.1 一级缓存:会话级别
    @Test
    public void testFindById(){
    // 获取代理对象
    UserMapper2 mapper = session.getMapper(UserMapper2.class);
    // 调用方法,通过主键查询
    // 先查询一级缓存,没有数据。
    // 会查数据库,都会有sql语句,把查询出来的数据存储到一级缓存中
    User user = mapper.findById(1);
    System.out.println(user);
    System.out.println("==================================");
    // 清除缓存
    // session.clearCache();
    // 在查询一次
    // 先查询一级缓存,存在数据。
    // 从缓存中把数据返回,就没有sql语句
    User user1 = mapper.findById(1);
    // 这两个user对象地址一样
    System.out.println(user1);
    }
    }

二级缓存

级别: SqlSessionFactory级别
需要手动开启二级缓存:

  • 在主配置文件开启二级缓存
    <!--配置延迟加载--><settings><!-- 开启延迟加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- 将积极加载改为消极加载及按需加载 --><setting name="aggressiveLazyLoading" value="false"/><!--开启二级缓存--><setting name="cacheEnabled" value="true"/></settings>
  • 在子配置文件开启二级缓存
    <!--开启二级缓存--><cache/>

除此之外,还有一个重要的条件:

  • 实体类一定要继承Serializable对象流

实操案例:

  • 测试代码
// 4.2 二级缓存:会话工厂级别
// 二级缓存的使用对象地址不同,但是也是从缓存加载。原因是二级缓存存储的是零散数据,组装出来的对象
@Test
public void testFindById2(){
// 获取代理对象
UserMapper2 mapper = session.getMapper(UserMapper2.class);
// 调用方法,通过主键查询
// 先查询一级缓存,没有数据。
// 会查数据库,都会有sql语句,把查询出来的数据存储到一级缓存中
User user = mapper.findById(1);
System.out.println(user);
System.out.println("==================================");
// 关闭会话
session.close();
// 获取session对象 和 获取代理对象
session = factory.openSession();
UserMapper2 mapper1 = session.getMapper(UserMapper2.class);
// 在查询一次
// 先查询一级缓存,存在数据。
// 从缓存中把数据返回,就没有sql语句
User user1 = mapper1.findById(1);
// 这两个user对象地址一样
System.out.println(user1);
}

二级缓存

http://www.jsqmd.com/news/298665/

相关文章:

  • 深聊氨基酸洗发产品,好用的品牌都在这了
  • auto类型和范围for循环
  • 导师推荐2026最新!9款AI论文工具测评:专科生毕业论文必备
  • Java毕设选题推荐:基于 SpringBoot 的网上鲜花销售花店管理系统的设计与实现 基于springboot的鲜花销售管理系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • Java毕设选题推荐:基于springboot的社区独居老人健康管理系统社区空巢老人健康管理系统 【附源码、mysql、文档、调试+代码讲解+全bao等】
  • BERT微调加速
  • 2005-2024年上市公司管理者短视主义数据+stata代码
  • 2007-2024年上市公司媒体关注日、年数据
  • 2010-2024年地级市新质生产力数据
  • 详细介绍:【C++入门必备】 最详细安装入门教程(一)
  • 总结国内认证权威的芳疗师培训学校,爱芙悦芳疗学院实力强劲
  • 2025年热转印机选购必看:高口碑实力厂商全解析,服务好的热转印机品牌精选综合实力TOP企业
  • 2025年度上海防疫物资回收企业推荐:环保贡献突出,隔离衣回收/防护服回收/防疫物资回收,防疫物资回收机构排行榜单
  • Java毕设项目推荐-基于springboot+vue的鲜花盆栽绿植销售系统设计与实现基于springboot的鲜花销售管理系统的设计与实现【附源码+文档,调试定制服务】
  • 盘点苏州电动升降机生产厂技术强的有哪些,推荐靠谱厂家
  • 年升降平台哪个制造商质量过硬,这几家值得关注
  • 升降平台制造厂哪家合作案例多,无锡靠谱厂家推荐
  • [Tools] Using Cloudflared to expose your local server to public
  • 留香持久沐浴露推荐,恋香花语性价比高的产品怎么选?
  • Java毕设项目:基于springboot的鲜花销售管理系统的设计与实现(源码+文档,讲解、调试运行,定制等)
  • 【毕业设计】基于springboot的鲜花销售管理系统的设计与实现(源码+文档+远程调试,全bao定制等)
  • 【课程设计/毕业设计】基于SpringBoot框架的在线鲜花管理系统基于springboot的鲜花销售管理系统的设计与实现【附源码、数据库、万字文档】
  • 计算机毕业设计springboot反诈普法平台 基于 SpringBoot 的全民防骗法律知识共享平台 智慧反诈教育学习与举报一体化系统
  • DDR3带宽计算
  • 2025年本地工程师推荐的无线电综合测试仪榜单,光纤熔接机/雷达干扰模拟器/光通信测量仪表无线电综合测试测试仪公司推荐排行榜
  • 计算机毕业设计springboot防诈骗安全知识信息管理系统 基于SpringBoot的全民反诈知识学习与预警平台 智慧防骗安全教育及案例分享系统
  • 计算机毕业设计springboot方剂服药衍变历史信息系统 基于SpringBoot的中医方剂演变知识图谱系统 中药复方历史变迁与临床衍化信息平台
  • Windows系统C盘爆红问题解决方案
  • 哪款电脑清理软件最好?C盘变红了怎么办?C盘爆红清理软件
  • 疲劳试验机团队专业的厂家哪个口碑好