延迟加载的定义
就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载
优点
先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
缺点
因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。
首先我们需要在主配值文件中加上这一段话
<settings>
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--关闭即时加载 在mybatis3.4.1以后 默认就是关闭的-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
一对一延迟加载
首先我们要有两张表
一张user表
一张account表
因为是一对一查询 那么显然一个账户对应一个用户
因此我们在配置文件中加上以下内容
<resultMap id="AccountUserMapper" type="com.tubai.domain.Account">
<id property="ID" column="id"></id>
<result property="UID" column="uid"></result>
<result property="money" column="money"></result>
<!--根据查询出来的uid作为参数传递给select中的方法-->
<association property="user" column="uid" javaType="com.tubai.domain.User"
select="com.tubai.dao.UserDao.findUserByID">
</association>
</resultMap>
<select id="selectAll" resultMap="AccountUserMapper">
select * from account;
</select>
这是Accout类的属性
private Integer ID;
private Integer UID;
private Double money;
//与用户建立一对一的联系
private User user;
这是User类的属性
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
//这个是一对多查询的部分使用到的 这里暂时忽略
private List<Account> accountList;
思考
可以发现我们的采用延迟加载的话,我们的sql语句是非常简洁的,仅仅是单纯的查询所有而已,并不存在其他的外连接什么的复杂sql。
那么我们是如何完成延迟查询的呢?
我们发现我们的association标签中有一个属性select
select="com.tubai.dao.UserDao.findUserByID"
这个属性调用了一个方法,这个方法是通过用户id来查询用户的
那么参数从哪来?我们发现属性中还有一个叫
column="uid"
破案了,Mybatis就是在需要用到用户信息的时候 ,才会去调用我们提供的方法。这样就成功实现了懒加载
测试
我们写一个测试方法
@Test
public void testSelectAll() throws Exception{
List<Account> accounts = accountDao.selectAll();
for (Account account : accounts) {
System.out.println(account);
System.out.println(account.getUser());
}
}
执行,我们从控制台中发现和立即加载没有任何区别
是因为我们这里使用到了account
如果我们将使用到account的部分注释掉
变成以下形式
@Test
public void testSelectAll() throws Exception{
List<Account> accounts = accountDao.selectAll();
for (Account account : accounts) {
//System.out.println(account);
//System.out.println(account.getUser());
}
}
再一次执行 我们发现延迟加载的效果就出现了
并没有去查询关于user的部分(因为我们没有使用到,也就不需要去访问了)
一对多延迟加载
一个用户可以拥有多个账户 那么我们仿照上面的思路
我们可以写下这样的配置文件
<resultMap id="userAccountMap" type="com.tubai.domain.User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
<result property="birthday" column="birthday"></result>
<!--使用集合存储则需要用collection-->
<!--ofType是指集合中的每个元素是什么-->
<collection property="accountList" ofType="com.tubai.domain.Account"
select="com.tubai.dao.AccountDao.findAccountByUid" column="id">
</collection>
</resultMap>
<select id="selectAll" resultMap="userAccountMap">
select * from user
</select>
同样的和一对一查询进行测试
@Test
public void testSelectAll()throws Exception{
List<User> users = userDao.selectAll();
//一对多延迟加载 当访问到user的时候 才会动态的调用查询语句 来给accountList赋值
for (User user : users) {
System.out.println("每个用户的信息");
System.out.println(user);
System.out.println(user.getAccountList());
}
}
@Test
public void testSelectAll()throws Exception{
List<User> users = userDao.selectAll();
//一对多延迟加载 当访问到user的时候 才会动态的调用查询语句 来给accountList赋值
for (User user : users) {
/*System.out.println("每个用户的信息");
System.out.println(user);
System.out.println(user.getAccountList());*/
}
}
通过以上测试 我们就能简易的明白延迟加载及其使用了