zoukankan      html  css  js  c++  java
  • MyBatis分步查询的延迟加载

    • 延迟加载的概念只存在于分步查询时;
    • 延迟加载的本质是为第一步查询返回的Java Bean创建了一个代理对象;
    • 延迟加载的全局设置有两个:
      • lazyLoadingEnabled,作用为设置select语句的默认延迟加载是否开启;
      • aggressiveLazyLoading,对于开启了延迟加载的select作用如下:

        • 值为true时,假设select返回的Java Bean为xxx,那么获取任何xxx属性的动作都会导致resultMap中定义的所有关联查询马上执行;
        • 值为false时,假设yyy为xxx的一个属性,由关联查询获取,那么只有在yyy的某一属性被使用时,获取yyy的关联查询才会执行
    • 延迟加载针对单个查询的具体设置为resultMap的 fetchType属性;
    • 全局设置lazyLoadingEnabled和具体设置fetchType的关系如下:
      • 如果设置了resultMap的 fetchType属性,那么全局设置lazyLoadingEnabled便不再对该select生效,是否延迟加载要以fetchType属性为准;
      • 如果select的resultMap没有设置 fetchType属性,那么该select会采用lazyLoadingEnabled的设置;
      • aggressiveLazyLoading只对延迟加载的select生效

    演示如下

    需要注意的是,一下演示在DEBUG模式下不成立,均为RUN模式;DEBUG模式下(IDEA环境)MyBatis不会延迟加载

    E-R图:一个City隶属于一个Country,同时一个City包含多个Address

    实体类:CityPlusPlus中包含一个Country和多个Address

    CityPlusPlus

    public class CityPlusPlus {
        private Long id;
        private String name;
        private Long countryId;
        private Date lastUpdate;
        private Country country;
        private List<Address> addressList;
    }

    Country

    public class Country {
        Long id;
        String name;
        Date lastUpdate;
    }

    Address

    public class Address {
        Long addressId;
        String address;
        String address2;
        String district;
        String postalCode;
        String phone;
        Long cityId;
        Location location;
        Date lastUpdate;
    }

    lazyLoadingEnabled和aggressiveLazyLoading均为true,fetchType不设置

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC  "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="canger.study.chapter04.mapper.CityPlusPlusMapper">
    
        <resultMap id="cityPlusPlusResultMap" type="canger.study.chapter04.bean.CityPlusPlus">
            <id column="city_id" property="id"/>
            <result column="city" property="name"/>
            <result column="country_id" property="countryId"/>
            <result column="last_update" property="lastUpdate"/>
            <association property="country"
                         select="canger.study.chapter04.mapper.CountryMapper.selectCountryById"
                         column="country_id"/>
            <association property="addressList"
                         select="canger.study.chapter04.mapper.AddressMapper.selectAddressesByCityId"
                         column="city_id"/>
        </resultMap>
    
        <select id="selectCityPlusPlusById" resultMap="cityPlusPlusResultMap">
            select *
            from city
            where city_id=#{id}
        </select>
    </mapper>
        <settings>
            <setting name="mapUnderscoreToCamelCase" value="true"/>
            <setting name="lazyLoadingEnabled" value="true"/>
            <setting name="aggressiveLazyLoading" value="true"/>
        </settings>

    测试代码如下:

        @Test
        public void testCityPlusPlusMapper(){
            SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.initSqlSessionFactory();
            SqlSession sqlSession = null;
    
            try {
                sqlSession = sqlSessionFactory.openSession();
                CityPlusPlusMapper mapper = sqlSession.getMapper(CityPlusPlusMapper.class);
                System.out.println("************开始主动查询**************");
                CityPlusPlus cityPlusPlus = mapper.selectCityPlusPlusById(42L);
                System.out.println("*************主动查询结束*************");
                System.out.println(cityPlusPlus.getName());
                System.out.println("*************Step2*************");
                System.out.println(cityPlusPlus.getCountry());
                System.out.println("**************Step3************");
                System.out.println(cityPlusPlus.getAddressList());
                System.out.println();
                System.out.println();
                sqlSession.commit();
            } catch (Exception e) {
                e.printStackTrace();
                sqlSession.rollback();
            } finally {
                sqlSession.close();
            }
        }

     日志输出如下,可以看到,当调用 cityPlusPlus.getName() 时,两个关联查询均马上执行

    ************开始主动查询**************
    [DEBUG] 2018-11-21 23:37:12,307(300) --> [main] org.apache.ibatis.transaction.jdbc.JdbcTransaction.openConnection(JdbcTransaction.java:137): Opening JDBC Connection  
    [DEBUG] 2018-11-21 23:37:12,552(545) --> [main] org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:406): Created connection 1514160588.  
    [DEBUG] 2018-11-21 23:37:12,553(546) --> [main] org.apache.ibatis.transaction.jdbc.JdbcTransaction.setDesiredAutoCommit(JdbcTransaction.java:101): Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5a4041cc]  
    [DEBUG] 2018-11-21 23:37:12,555(548) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): ==>  Preparing: select * from city where city_id=?   
    [DEBUG] 2018-11-21 23:37:12,575(568) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): ==> Parameters: 42(Long)  
    [DEBUG] 2018-11-21 23:37:12,631(624) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): <==      Total: 1  
    *************主动查询结束*************
    [DEBUG] 2018-11-21 23:37:12,632(625) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): ==>  Preparing: select * from country where country_id=?   
    [DEBUG] 2018-11-21 23:37:12,637(630) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): ==> Parameters: 103(Integer)  
    [DEBUG] 2018-11-21 23:37:12,640(633) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): <==      Total: 1  
    [DEBUG] 2018-11-21 23:37:12,641(634) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): ==>  Preparing: select address_id,address,address2,district,city_id,postal_code,phone,astext(location) as location,last_update from address where city_id=?   
    [DEBUG] 2018-11-21 23:37:12,641(634) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): ==> Parameters: 42(Integer)  
    [DEBUG] 2018-11-21 23:37:12,651(644) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): <==      Total: 2  
    Aurora
    *************Step2*************
    Country{id=103, name='United States', lastUpdate=Wed Feb 15 04:44:00 CST 2006}
    **************Step3************
    [Address{addressId=335, address='587 Benguela Manor', address2='', district='Illinois', postalCode='91590', phone='165450987037', cityId=42, location=POINT(-88.3200762 41.760583), lastUpdate=Thu Sep 25 22:33:44 CST 2014}, Address{addressId=543, address='43 Vilnius Manor', address2='', district='Colorado', postalCode='79814', phone='484500282381', cityId=42, location=POINT(-104.8319273 39.729439), lastUpdate=Thu Sep 25 22:33:44 CST 2014}]

     lazyLoadingEnabled为true和aggressiveLazyLoading为false,fetchType不设置

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

    输出日志,可以看到:

    • 当调用cityPlusPlus.getCountry() 时,第一个关联查询执行
    • 当调用cityPlusPlus.getAddressList()时,第二个关联查询执行
    ************开始主动查询**************
    [DEBUG] 2018-11-21 23:56:04,599(286) --> [main] org.apache.ibatis.transaction.jdbc.JdbcTransaction.openConnection(JdbcTransaction.java:137): Opening JDBC Connection  
    [DEBUG] 2018-11-21 23:56:04,829(516) --> [main] org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:406): Created connection 1514160588.  
    [DEBUG] 2018-11-21 23:56:04,830(517) --> [main] org.apache.ibatis.transaction.jdbc.JdbcTransaction.setDesiredAutoCommit(JdbcTransaction.java:101): Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5a4041cc]  
    [DEBUG] 2018-11-21 23:56:04,844(531) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): ==>  Preparing: select * from city where city_id=?   
    [DEBUG] 2018-11-21 23:56:04,865(552) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): ==> Parameters: 42(Long)  
    [DEBUG] 2018-11-21 23:56:04,941(628) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): <==      Total: 1  
    *************主动查询结束*************
    Aurora
    *************Step2*************
    [DEBUG] 2018-11-21 23:56:04,942(629) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): ==>  Preparing: select * from country where country_id=?   
    [DEBUG] 2018-11-21 23:56:04,943(630) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): ==> Parameters: 103(Integer)  
    [DEBUG] 2018-11-21 23:56:04,956(643) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): <==      Total: 1  
    Country{id=103, name='United States', lastUpdate=Wed Feb 15 04:44:00 CST 2006}
    **************Step3************
    [DEBUG] 2018-11-21 23:56:04,961(648) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): ==>  Preparing: select address_id,address,address2,district,city_id,postal_code,phone,astext(location) as location,last_update from address where city_id=?   
    [DEBUG] 2018-11-21 23:56:04,961(648) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): ==> Parameters: 42(Integer)  
    [DEBUG] 2018-11-21 23:56:04,971(658) --> [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159): <==      Total: 2  
    [Address{addressId=335, address='587 Benguela Manor', address2='', district='Illinois', postalCode='91590', phone='165450987037', cityId=42, location=POINT(-88.3200762 41.760583), lastUpdate=Thu Sep 25 22:33:44 CST 2014}, Address{addressId=543, address='43 Vilnius Manor', address2='', district='Colorado', postalCode='79814', phone='484500282381', cityId=42, location=POINT(-104.8319273 39.729439), lastUpdate=Thu Sep 25 22:33:44 CST 2014}]
  • 相关阅读:
    打包spring项目遇到的坑 Unable to locate Spring NamespaceHandler for XML schema ……shcema/context 产生的原因及解决方法
    Mybatis 从入门到精通一:mybatis的入门
    IO流系列一:输入输出流的转换
    本地模拟 gitlab ci 的 demo 项目
    docker 容器中部署 Go 服务时,请求 https 文件时抛错
    微信支付『支付失败,如果已扣款,资金在0-3个工作日原路返回』踩坑案例及解决方案
    PHP 安装 扩展时 抛出 /usr/local/Cellar/php@7.1/7.1.25/pecl 异常解决
    SpringBoot2 引入 Aop
    Mac 下 IDEA 中 SpringBoot 如何利用 DevTool 开启热部署
    MySql数据库中敏感字段加密处理方案
  • 原文地址:https://www.cnblogs.com/canger/p/9997793.html
Copyright © 2011-2022 走看看