• MyBatis中的延迟加载与分步查询


    MyBatis中,延迟加载(Lazy Loading)是一种优化数据库访问的技术,它允许我们在真正需要访问关联对象的数据时才执行相应的SQL查询。这种机制特别适用于处理复杂对象关系映射(ORM)时,可以有效地减少不必要的数据库访问,从而提高应用程序的性能。

    分步查询与延迟加载

    分步查询是延迟加载的一种实现方式,它允许我们将一个复杂的查询分解为多个简单的查询,并根据需要逐个执行。在MyBatis中,我们可以通过在 标签中使用 标签,并指定 select 属性来实现分步查询。

    为了启用延迟加载,我们需要在MyBatis的核心配置文件中设置两个全局配置参数:

    • lazyLoadingEnabled:该参数用于开启或关闭延迟加载的全局开关。

      • 当设置为true时,所有关联对象都会采用延迟加载的方式。
    • aggressiveLazyLoading:该参数用于控制延迟加载的行为。

      • 当设置为true时,任何对对象方法的调用都会导致加载该对象的所有属性(包括关联对象)。
      • 当设置为false时,每个属性都会按需加载。

    此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过 associationcollection 中的 fetchType 属性设置当前的分步查询是否使用延迟加载,fetchType="lazy(延迟加载)|eager(立即加载)"

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

    示例

    假设我们有一个员工(Emp)和部门(Dept)的关联关系,员工对象包含一个部门对象的引用。我们可以使用分步查询来实现员工和部门的延迟加载。

    首先,在MyBatis的配置文件中启用延迟加载:

    <settings>  
        <setting name="lazyLoadingEnabled" value="true"/>  
          
        <setting name="aggressiveLazyLoading" value="false"/>  
    settings>
    

    然后,在映射文件(Mapper XML)中定义分步查询的

    <resultMap id="empAndDeptByStepResultMap" type="Emp">
    	<id property="eid" column="eid">id>
    	<result property="empName" column="emp_name">result>
    	<result property="age" column="age">result>
    	<result property="sex" column="sex">result>
    	<result property="email" column="email">result>
    	<association property="dept"
    				 select="com.example.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
    				 column="did"
    				 fetchType="lazy">association>
    resultMap>
    

    注意,在 标签中,我们指定了select属性为获取部门信息的SQL语句ID,column 属性为传递给该SQL语句的参数(即员工的部门ID),并设置了 fetchTypelazy 以启用延迟加载。

    之后,编写测试的java语句

    @Test
    public void getEmpAndDeptByStepOne() {
    	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
    	Emp emp = mapper.getEmpAndDeptByStepOne(1);
    	System.out.println(emp.getEmpName());
    }
    
    • 关闭延迟加载,两条SQL语句都运行了延迟加载测试1
    • 开启延迟加载,只运行获取emp的SQL语句

    延迟2

    @Test
    public void getEmpAndDeptByStepOne() {
    	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
    	Emp emp = mapper.getEmpAndDeptByStepOne(1);
    	System.out.println(emp.getEmpName());
    	System.out.println("----------------");
    	System.out.println(emp.getDept());
    }
    
    • 开启延迟加载后,需要用到查询dept的时候才会调用相应的SQL语句

    延迟3

    在Java代码中,当我们通过 mapper.getEmpAndDeptByStepOne(1) 获取员工信息时,MyBatis只会执行查询员工信息的SQL语句。当我们真正需要访问员工关联的部门信息时(例如通过emp.getDept()),MyBatis才会执行查询部门信息的SQL语句。

    总结

    MyBatis的分步查询延迟加载机制允许我们灵活地控制数据库访问的时机和方式,从而优化应用程序的性能。通过合理地使用这些机制,我们可以减少不必要的数据库访问,提高应用程序的响应速度和用户体验。同时,我们也需要注意避免过度使用延迟加载,以免导致“N+1查询问题”等性能问题。

  • 相关阅读:
    淘宝API接口大全
    QGraphicsView实现拖拽缩放
    Vue开发时Vscode建议安装的常用插件
    一个简单高效低内存的.NET操作Excel开源框架 - MiniExcel
    从拜占庭将军问题到分布式系统的一致性
    torch.nn中的L1Loss和MSELoss
    盲盒小程序有哪些特色功能
    Turtlebot3-burger入门教程#foxy版#-软件清单
    vscode提交git代码总是需要输入账号密码问题
    共模干扰、差模干扰 以及运放共模抑制比(Common-mode rejection ratio, CMRR)
  • 原文地址:https://blog.csdn.net/Zachyy/article/details/139717164