Java第三十七天,Mybatis框架系列,延迟加载
延迟加载
1.定义
在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载
2.好处
先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快
3.坏处
因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间
4.策略
一对一:立即加载(通常情况下行业规则,不一定)
多对多:延迟加载(通常情况下行业规则,不一定)
5.在数据库配置文件 sqlMapConfig.xml 中开启 mybatis 延迟的全局开关
配置方法:
依次进入:
1.https://mybatis.org/mybatis-3/zh/index.html
2.XML 配置
3.settings(设置)
lazyLoadingEnabled ===> 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态
aggressiveLazyLoading ===> 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载
开始配置:
<settings>
<!--开启Mybatis支持延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"></setting>
</settings>
6.示例
(1)实体类——User 类、Account 类
package com.lanyue.domain;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @author 黑马程序员
* @Company
*/
public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
//一对多关系映射:主表实体应该包含从表实体的集合引用
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", address='" + address + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
'}';
}
}
package com.lanyue.domain;
import java.io.Serializable;
/**
* @author 黑马程序员
* @Company
*/
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
//从表实体应该包含一个主表实体的对象引用
private User user;
public User getUser() {
return user;
}
public void setUser(User 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 "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
'}';
}
}
(2)功能接口——IUserDao、IAccountDao
package com.lanyue.dao;
import com.lanyue.domain.Account;
import java.util.List;
/**
* @author 黑马程序员
* @Company
*/
public interface IAccountDao {
/**
* 查询所有账户,同时还要获取到当前账户的所属用户信息
* @return
*/
List<Account> findAll();
/**
* 根据用户id查询账户信息
* @param uid
* @return
*/
List<Account> findAccountByUid(Integer uid);
}
(3)接口实现配置文件——IUserDao.xml、IAccountDao.xml
注意配置文件中的以下内容,只有代码中用到被 association或collection 标签的 property 属性绑定的类属性时,才会执行 association或collection 标签中的 select 指定的方法
<!--一对一,多对一(在 mybatis 中还是一对一)-->
<association property="" column="" javaType="" select=""></association>
<!--一对多-->
<collection property="" ofType="" select="" column=""></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.lanyue.dao.IUserDao">
<!-- 一对多的关系映射-->
<!-- 定义User的resultMap-->
<resultMap id="userAccountMap" type="user">
<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>
<!-- 配置user对象中accounts集合的映射 -->
<collection property="accounts" ofType="account" select="com.lanyue.dao.IAccountDao.findAccountByUid" column="id"></collection>
</resultMap>
<!-- 查询所有 -->
<select id="findAll" resultMap="userAccountMap">
select * from user
</select>
<!-- 根据id查询用户 -->
<select id="findById" parameterType="INT" resultType="user">
select * from user where id = #{uid}
</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.lanyue.dao.IAccountDao">
<!-- 定义封装account和user的resultMap -->
<resultMap id="accountUserMap" type="account">
<id property="id" column="id"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!--
一对一的关系映射:配置封装user的内容
select属性指定的内容:查询用户的唯一标识;即 Dao 层接口定义的方法
column属性指定的内容:用户根据id查询时,所需要的参数的值;即 select 语句的 findById 中 By 的究竟是上述查询结果中的哪个字段
-->
<association property="user" column="uid" javaType="user" select="com.lanyue.dao.IUserDao.findById"></association>
</resultMap>
<!-- 查询所有 -->
<select id="findAll" resultMap="accountUserMap">
select * from account
</select>
<!-- 根据用户id查询账户列表 -->
<select id="findAccountByUid" resultType="account">
select * from account where uid = #{uid}
</select>
</mapper>