myBatis中的延迟加载介绍

1、myBatis的延迟加载一般使用在一对多、一对一的场景中,即一些信息当需要时才会去加载;
相对的也就有即时加载,主要在多对一,多对多场景中使用。
2、一对一场景下实现延迟加载
2.1、myBatis配置文件中的配置:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <properties url="file:///E:/Idea/MyBatis01/src/main/resources/jdbcConfig.properties">
    </properties>

    <!--设置延迟加载开关-->
    <!--配置参数,此处需要注意settings标签要优先于typeAliases标签-->
    <settings>
        <!--开启Mybatis支持延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

    <typeAliases>
        <package name="Model"></package>
    </typeAliases>


    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置连接数据库的必备信息  type属性表示是否使用数据源(连接池)
                property标签中value属性值java:comp/env/  此为固定写法  ;
                jdbc/mybatis 数据源名称(在META-INF中的配置文件中配置的数据)
            -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--此处使用package标签配置映射需要注意,接口映射文件与SQL映射文件必须是一一对应的,不然编译会出现异常-->
        <package name="myBatis.dao"></package>
    </mappers>
</configuration>

2.2、SQL映射文件配置:

<?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="myBatis.dao.JNDIMapper">
    <resultMap id="userAccountJNDI" type="userAcountJNDI">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="address" column="address"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <collection property="accounts" ofType="account">
            <id property="id" column="aid"></id>
            <result property="uid" column="UID"></result>
            <result property="money" column="MONEY"></result>
        </collection>
    </resultMap>
    <!--账户与用户一一对应的关系:
        此处主要是实现一一对应关系的懒加载(延迟加载)
    -->
    <resultMap id="accountUser" type="accountUsermodel">
        <id property="id" column="id"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!--此处的column属性必须写,属性的值作为select属性中引用的查询sql的参数-->
        <association property="user" column="uid" javaType="userCRUDmodeltwo" select="myBatis.dao.IUserCRUDDao.queryUserInfoById"></association>
    </resultMap>

    <select id="getAllUserInfo" resultMap="userAccountJNDI">
        SELECT u.*,
               a.id aid,
               a.UID,
               a.MONEY
        FROM user u
        left join account a
        on a.UID = u.id
    </select>

    <select id="getAccountUserByLazy" resultMap="accountUser">
        select * from account
    </select>
</mapper>

上述延迟加载是引用的SQL为根据id查询用户信息:
在这里插入图片描述
在这里插入图片描述
2.3、封装实体类:

package Model;

/**
 * 账户-人员  一对一的关系加载
 */
public class accountUserModel {
    private Integer id;
    private Integer uid;
    private Double money;

    private userCRUDModelTwo user;

    public userCRUDModelTwo getUser() {
        return user;
    }

    public void setUser(userCRUDModelTwo user) {
        this.user = user;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "accountUserModel{" +
                "id=" + id +
                ", uid=" + uid +
                ", money=" + money +
                ", user=" + user +
                '}';
    }
}

3、测试方法:

InputStream in=null;
        SqlSessionFactoryBuilder ssfb = null;
        SqlSessionFactory ssf = null;
        SqlSession ss = null;
        JNDIMapper jndi;


        //初始化操作
        @Before   //Junit注解,在@Test之前运行
        public void init() throws IOException {
            in = Resources.getResourceAsStream("MyBatis_LAZY.xml");

            ssfb = new SqlSessionFactoryBuilder();
            ssf = ssfb.build(in);

            ss = ssf.openSession();

            jndi = ss.getMapper(JNDIMapper.class);
        }

        //释放资源,在@Tes之后运行
        @After
        public void close() throws IOException {
            ss.commit();//提交操作,此处要注意设置,此处默认没有自动提交
            ss.close();
            in.close();
        }

        /**
         * 查询操作
         */
        @Test
        public void queryAccountUserByLazy(){

            List<accountUserModel> list = jndi.getAccountUserByLazy();
            for ( accountUserModel accountUser:list
                 ) {
                System.out.println(accountUser);
                //System.out.println(accountUser.getUser());  //触发加载用户信息(延迟加载的信息)
            }

        }

**4、**此处需要注意的是,在配置文件中配置延迟加载的开关是需要用到CGLIB包,不然会报错:

org.apache.ibatis.exceptions.PersistenceException: 
### Error building SqlSession.
### The error may exist in SQL Mapper Configuration
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.lang.IllegalStateException: Cannot enable lazy loading because CGLIB is not available. Add CGLIB to your classpath.

	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:23)
	at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:79)
	at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:63)
	at myBatisDemo.JNDITest.init(JNDITest.java:35)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.lang.IllegalStateException: Cannot enable lazy loading because CGLIB is not available. Add CGLIB to your classpath.
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:106)
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:89)
	at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:77)
	... 25 more
Caused by: java.lang.IllegalStateException: Cannot enable lazy loading because CGLIB is not available. Add CGLIB to your classpath.
	at org.apache.ibatis.executor.loader.CglibProxyFactory.<init>(CglibProxyFactory.java:50)
	at org.apache.ibatis.session.Configuration.setLazyLoadingEnabled(Configuration.java:275)
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.settingsElement(XMLConfigBuilder.java:199)
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:100)
	... 27 more
Caused by: java.lang.ClassNotFoundException: Cannot find class: net.sf.cglib.proxy.Enhancer
	at org.apache.ibatis.io.ClassLoaderWrapper.classForName(ClassLoaderWrapper.java:188)
	at org.apache.ibatis.io.ClassLoaderWrapper.classForName(ClassLoaderWrapper.java:87)
	at org.apache.ibatis.io.Resources.classForName(Resources.java:254)
	at org.apache.ibatis.executor.loader.CglibProxyFactory.<init>(CglibProxyFactory.java:48)

此时需要在pom.xml文件中引入包CGLIB:

<dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.2.5</version>
    </dependency>

5、扩展:一对多的延迟加载配置:
SQL映射文件配置:

 <!--用户与账户信息 一对多的关系:
        主要实现一对多关系的延迟加载
    -->
    <resultMap id="userAccountLazy" type="userAcountJNDI">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="address" column="address"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <collection property="accounts" ofType="account" select="myBatis.dao.JNDIMapper.getAccountByUId" column="id">
        </collection>
    </resultMap>
    ----------------------------------------------
<select id="getQueryAllUserAccountByLazy" resultMap="userAccountLazy">
        select * from user
    </select>
-------------------------------------------------------
<resultMap id="accountResult" type="account">
        <id property="id" column="id"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
    </resultMap>
    <select id="getAccountByUId" resultMap="accountResult" parameterType="int">
        select * from account where uid = #{uid}
    </select>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值