在实际开发中,有的数据不需要立即加载,而是需要的时候再去加载,不需要用到的时候则不去加载,这就是延时加载,也称为按需加载(懒加载)。
-
利 : 提高数据库性能 弊 : 需要时候在查询,存在大批量的数据查询。
assocation的延时加载
要求:查询账户信息,同时按需加载用户信息。
- 创建实体类
package com.liang.domain;
import java.io.Serializable;
/**
* 账户实体类
*/
public class Account implements Serializable {
private int id;
private int uid;
private Double money;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
'}';
}
}
package com.liang.domain;
import java.util.Date;
/**
* 用户类
*/
public class User {
private int id;
private String username;
private Date birthday;
private String sex;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
- 创建持久层接口
package com.liang.dao;
import com.liang.domain.Account;
import java.util.List;
/**
* 账户的持久层接口
*/
public interface AccountDao {
/**
* 查询所有账户信息,同时包含其用户信息
* @return
*/
List<Account> findAll();
}
package com.liang.dao;
public interface UserDao{
/**
* 根据id查询用户
* @param id
* @return
*/
User findById(int id);
}
- 编写持久层映射文件
<resultMap id="accountMap" type="com.liang.domain.Account">
<id property="id" column="id"></id>
<result column="uid" property="uid"></result>
<result column="money" property="money"></result>
<!--建立Account类中user属性对应的数据库表
column: 数据库中的列名,或者是列的别名。一般情况下,是我们传递给select映射的参数
select: 用于加载复杂类型属性的映射语句的 ID,它会从 column 属性指定的列中检索数据,作为参数传递给目标 select 语句。
-->
<association property="user" javaType="com.liang.domain.User" select="com.liang.dao.UserDao.findById" column="uid">
</association>
</resultMap>
<!--查询所有账户信息,同时包含其用户信息-->
<select id="findAll" resultMap="accountMap">
select *from account;
</select>
<!--根据id查询用户-->
<select id="findById" resultType="User" parameterType="int">
<include refid="querySql"></include> where id= #{userID};
</select>
- 编写测试方法
/**
* 查询所有账户信息,同时包含其用户信息【延迟加载】
*/
@Test
public void testFindAll()
{
List<Account> accounts = accountDao.findAll();
}
- 开启延迟加载策略
<settings>
<!--
lazyLoadingEnabled : 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。
aggressiveLazyLoading : 当开启时,任何方法的调用都会加载该对象的所有属性
-->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
此时执行程序的日志为:
而当没有延时加载时,程序执行日志为:
可以看出:当没有延时加载时候,采用的是立即加载策略。
collection的延时加载
要求:查询用户信息,同时按需加载账户信息。
- 编写实体类
package com.liang.domain;
import java.util.Date;
import java.util.List;
/**
* 用户类
*/
public class User {
private int id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
package com.liang.domain;
import java.io.Serializable;
/**
* 账户实体类
*/
public class Account implements Serializable {
private int id;
private int uid;
private Double money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
'}';
}
}
- 编写持久层接口类方法
package com.liang.dao;
import com.liang.domain.User;
import java.util.List;
public interface UserDao{
/**
* 查询所有用户
* @return
*/
List<User> findAll();
}
package com.liang.dao;
import com.liang.domain.Account;
import java.util.List;
/**
* 账户的持久层接口
*/
public interface AccountDao {
/**
* 通过用户id查询账户信息
* @param uid
* @return
*/
List<Account> findByUid(int uid);
}
- 编写持久层映射文件
<?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.liang.dao.UserDao">
<resultMap id="userMap" type="com.liang.domain.User">
<id column="id" property="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 property="accounts" select="com.liang.dao.AccountDao.findByUid" column="id"></collection>
</resultMap>
<select id="findAll" resultMap="userMap">
select *from user;
</select>
</mapper>
<?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.liang.dao.AccountDao">
<select id="findByUid" parameterType="int" resultType="com.liang.domain.Account">
select *from account where uid = #{uid}
</select>
</mapper>
- 编写测试方法
import com.liang.dao.UserDao;
import com.liang.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 TestMyBatis {
private SqlSession sqlSession = null;
private InputStream inputStream = null;
private UserDao userDao = null;
@Before
public void init() throws IOException {
inputStream = Resources.getResourceAsStream("SqlConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
sqlSession = sqlSessionFactory.openSession();
userDao = sqlSession.getMapper(UserDao.class);
}
@After
public void destroy() throws IOException {
sqlSession.commit();
sqlSession.close();
inputStream.close();
}
/**
* 查询所有用户信息
*/
@Test
public void testFindAll() {
List<User> users = userDao.findAll();
}
}
- 开启延迟加载策略
<settings>
<!--
lazyLoadingEnabled : 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。
aggressiveLazyLoading : 当开启时,任何方法的调用都会加载该对象的所有属性
-->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
经测试,开启延时加载时,程序执行日志为:
来源:CSDN
作者:李沐泽
链接:https://blog.csdn.net/Rong_zhe/article/details/103711716