一、一对一延迟加载
(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表,运行如下:
若让注释内生效,则会查询所有的用户下的所有账户信息并打印。
运行如下:(局部)
由此完成了一对多的延迟查询!
延迟查询告一段路。