SSM学习之路——Mybatis第四天_延迟加载策略

一、一对一延迟加载

(1)新建接口

在这里插入图片描述
在这里插入图片描述

(2)创建Account实体类

account实体类,根据数据库字段创建字段,并生成get&set&tostring
在这里插入图片描述
user实体类,……(同上)
在这里插入图片描述

(3) 编写xml文件

IAccountDao.xml如下
在这里插入图片描述

association注释如下代码:
注意此处的resultMap里,用作关联的标签为:<association>

<?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="com.itheima.dao.IAccountDao">
    <resultMap id="accountUserMap" type="account">
        <!--这一行的column为aid是因为,在下面查询语句,执行了 a.id as aid 的操作,所以这里对应的数据库字段应该为aid-->
        <id property="id" column="id"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>

        <!--此处  property为从表的数据表, javaType为映射到的实体类,
        select为要执行查询的方法的xml中的id:此处为对应IUserDao.xml中id为findById的select
        column对应的uid为要传过去的参数,此处为用户的id,对应UserDao.xml中的select要接收的参数名 即#{uid}
        -->
        <association property="user" column="uid" javaType="user" select="com.itheima.dao.IUserDao.findById">
        </association>
    </resultMap>
    <select id="findAll" resultMap="accountUserMap">
        select * from account;
    </select>

</mapper>

IUserDao.xml如下
在这里插入图片描述
此处接受一个IAccountDao.xml里面的sql语句传递过来的uid:

<select id="findById" resultType="user" parameterType="int">
        select * from user where id = #{uid}
    </select>
<?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="com.itheima.dao.IUserDao">
    <select id="findById" resultType="user" parameterType="int">
        select * from user where id = #{uid}
    </select>

</mapper>

(4)编写测试类

在这里插入图片描述

package com.itheima.test;

import com.itheima.dao.IAccountDao;
import com.itheima.dao.IUserDao;
import com.itheima.domain.Account;
import com.itheima.domain.User;
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 lazyLoadingTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    IAccountDao accountDao;
    @Before
    public void init() throws IOException {
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        session = factory.openSession();
        accountDao = session.getMapper(IAccountDao.class);
    }
    @After
    public void destroy () throws IOException {
        session.commit();
        in.close();
    }
    @Test
    public void testFindAll(){
        List<Account> accounts = accountDao.findAll();
//        for (Account account : accounts) {
//            System.out.println("--------------");
//            System.out.println(account);
//        }
    }
}

执行账户的查询所有方法,因为此方法会和用户id相关联起来,所以正常情况下会查询两个表,即account表和user表
但是我们现在看到,我们并没有用到user的相关信息(并没有要求打印出来,只是执行了查询account这张主表罢了,并没有用到和id相关联的user的信息)

接下来来看看这个的执行结果:

可以看到,我们在只写了List<Account> accounts = accountDao.findAll();的情况下,并没有对用户的信息进行操作(比如注释掉的打印部分),它还是查了两张表(user表和account表)。
由此降低了效率,因为我们并有用到,我们是想要在我们用到user表的时候,才去查user的相关信息。由此引入了延迟加载

在这里插入图片描述

(5)进行延迟加载设置

在SqlMapConfig.xml文件中,填入如下的<settings>

在这里插入图片描述
官网对这两个属性描述如下:
在这里插入图片描述
特别注意此处的<settings>要放在<properties>后,否则会报错
如:
在这里插入图片描述
再次执行
只对account表进行了查询。
在这里插入图片描述

如果我们将测试类中的注释内容有效,即查询账户信息,可以发现这个时候才真正查询到了两张表。

在这里插入图片描述

二、一对多查询

(1)user实体类

添加字段,并生成get&set方法,用于接收该用户所有的账户。

private List<Account> accounts;

(2)IUserDao接口

添加接收该id用户下的所有账户,传入用户id
在这里插入图片描述

(3)编写xml文件

IUserDao.xml文件:
注意这里关联为<collection>

<?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="com.itheima.dao.IUserDao">
    <!--编写对应的结果映射,映射字段到user实体类中-->
    <resultMap id="userMap" type="user">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
<!--        <collection>标签:  主要用于加载关联的集合对象 select 属性:  用于指定查询 account 列表的 sql 语句,所以填写的是该 sql 映射的 id -->
<!--      column 属性:  用于指定 select 属性的 sql 语句的参数来源,-->
<!--        参数来自于 user 的 id 列,所以就写成 id 这一 个字段名了-->
        <collection property="accounts" ofType="account"
                    select="com.itheima.dao.IAccountDao.findAccountById" column="id">
        </collection>
    </resultMap>
    <select id="findAll" resultMap="userMap">
        select * from user
    </select>

</mapper>

(4)编写测试类

import com.itheima.dao.IAccountDao;
import com.itheima.dao.IUserDao;
import com.itheima.domain.Account;
import com.itheima.domain.User;
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 lazyLoadingTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    IUserDao userDao;
    @Before
    public void init() throws IOException {
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        session = factory.openSession();
        userDao = session.getMapper(IUserDao.class);
    }
    @After
    public void destroy () throws IOException {
        session.commit();
        in.close();
    }
    @Test
    public void testFindAll(){
        List<User> users = userDao.findAll();
//        for (User u :users){
//            if (u.getAccounts().size() > 0){
//                System.out.println("-----------");
//                System.out.println(u);
//                System.out.println(u.getAccounts());
//            }
//        }
    }
}

这里没有用到account的信息,只查询了user表,运行如下:
在这里插入图片描述
若让注释内生效,则会查询所有的用户下的所有账户信息并打印。
运行如下:(局部)
在这里插入图片描述
由此完成了一对多的延迟查询!

延迟查询告一段路。

发布了23 篇原创文章 · 获赞 0 · 访问量 605

猜你喜欢

转载自blog.csdn.net/SixthMagnitude/article/details/104073266