1. 延迟加载
描述:延迟加载又名懒加载、按需加载,即我们需要这个数据的时候才去加载这个数据。在MyBatis框架中通过设置或标签的fetchType属性值为lazy来指按需加载。
需求:在用户与账户一对一关联查询的基础上,查询指定用户信息及其账户信息,对账户信息的查询实现延迟加载。
2. 数据库环境
2.1 表的创建
# 创建用户表
CREATE TABLE IF NOT EXISTS `user`(
`id` INT AUTO_INCREMENT,
`username` VARCHAR(32) NOT NULL,
`birthday` DATETIME NOT NULL,
`sex` CHAR(1) NOT NULL,
`address` VARCHAR(256),
CONSTRAINT pk_user PRIMARY KEY(`id`)
);
# 添加用户数据
INSERT INTO `user`(`id`,`username`,`birthday`,`sex`,`address`) VALUES
(NULL,'周瑜','2020-02-27 17:47:08','男','吴国'),
(NULL,'大乔','2020-02-27 15:09:37','女','吴国'),
(NULL,'小乔','2020-02-27 11:34:34','女','吴国'),
(NULL,'陆逊','2020-02-27 12:04:06','男','吴国'),
(NULL,'孙策','2020-02-27 17:37:26','男','东吴'),
(NULL,'孙尚香','2020-02-27 11:44:00','女','吴国'),
(NULL,'曹操','2020-07-29 16:36:26','男','魏国');
# 创建账户表
CREATE TABLE IF NOT EXISTS `account`(
`id` INT AUTO_INCREMENT,
`user_id` INT NOT NULL,
`money` DOUBLE NOT NULL,
CONSTRAINT pk_account PRIMARY KEY(`id`),
CONSTRAINT fk_account_user FOREIGN KEY(`user_id`) REFERENCES `user`(`id`)
);
# 添加账户数据
INSERT INTO `account`(`id`,`user_id`,`money`) VALUES
(1,6,1000),
(2,3,1000),
(3,1,2000);
2.2 表与表的关系
3. 用户实体类
package zw.mybatis.bean.domain;
import java.io.Serializable;
import java.util.Date;
/**
* @className UserDO
* @description 用户实体类
* @author 周威
* @date 2020-07-31 14:14
**/
public class UserDO implements Serializable
{
/* 用户编号 */
private Integer id;
/* 用户姓名 */
private String userName;
/* 用户生日 */
private Date birthday;
/* 用户性别 */
private String sex;
/* 用户地址 */
private String address;
/* Getter和Setter方法 */
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 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;
}
/* toString()方法 */
@Override
public String toString()
{
return "UserDO{" + "id=" + id + ", userName='" + userName + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + '}';
}
}
4. 账户实体类
package zw.mybatis.bean.domain;
import java.io.Serializable;
/**
* @className AccountDO
* @description 账户实体类
* @author 周威
* @date 2020-08-07 14:03
**/
public class AccountDO implements Serializable
{
/* 账户编号 */
private Integer id;
/* 用户编号 */
private Integer userId;
/* 账户金额 */
private Double money;
/* Getter和Setter方法 */
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public Integer getUserId()
{
return userId;
}
public void setUserId(Integer userId)
{
this.userId = userId;
}
public Double getMoney()
{
return money;
}
public void setMoney(Double money)
{
this.money = money;
}
/* toString()方法 */
@Override
public String toString()
{
return "AccountDO{" + "id=" + id + ", userId=" + userId + ", money=" + money + '}';
}
}
5. 用户展示实体类
package zw.mybatis.bean.vo;
import zw.mybatis.bean.domain.AccountDO;
import zw.mybatis.bean.domain.UserDO;
import java.io.Serializable;
/**
* @className UserVO
* @description 用户展示实体类
* @author 周威
* @date 2020-08-03 18:31
**/
public class UserVO extends UserDO implements Serializable
{
/* 账户信息 */
private AccountDO accountDO;
/* Getter和Setter方法 */
public AccountDO getAccountDO()
{
return accountDO;
}
public void setAccountDO(AccountDO accountDO)
{
this.accountDO = accountDO;
}
/* toString()方法 */
@Override
public String toString()
{
return "UserVO{userDO="+ super.toString() + "accountDO=" + accountDO + '}';
}
}
6. 账户持久层接口
package zw.mybatis.mapper;
import zw.mybatis.bean.domain.AccountDO;
/**
* @className AccountMapper
* @description 账户持久层接口
* @author 周威
* @date 2020-08-07 14:06
**/
public interface AccountMapper
{
/**
* 查询账户信息,根据用户编查询指定账户信息
* @param userId
* @return 账户信息
*/
AccountDO findAccountInformationByUserId(Integer userId);
}
7. 账户映射文件
<?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="zw.mybatis.mapper.AccountMapper">
<!-- 输出映射 -->
<resultMap id="accountDOResultMap" type="zw.mybatis.bean.domain.AccountDO">
<id column="id" property="id" javaType="java.lang.Integer"/>
<result column="userId" property="userId" javaType="java.lang.Integer"/>
<result column="money" property="money" javaType="java.lang.Double"/>
</resultMap>
<!-- 查询账户信息,根据用户编查询指定账户信息 -->
<select id="findAccountInformationByUserId" parameterType="java.lang.Integer" resultMap="accountDOResultMap">
select
id id,
user_id userId,
money money
from
account
where
user_id = #{userId}
</select>
</mapper>
8. 用户持久层接口
package zw.mybatis.mapper;
import zw.mybatis.bean.vo.UserVO;
/**
* @className UserMapper
* @description 用户持久层接口
* @author 周威
* @date 2020-07-31 14:18
**/
public interface UserMapper
{
/**
* 查询用户信息,根据用户编号查询用户信息及其账户信息,实现账户信息查询的延迟加载
* @param userId
* @return 用户信息
*/
UserVO findUserInformationAndAccountByUserId(Integer userId);
}
9. 用户映射文件
<?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="zw.mybatis.mapper.UserMapper">
<!-- 输出映射 -->
<resultMap id="userVOResultMap" type="zw.mybatis.bean.vo.UserVO">
<!-- 用户信息映射 -->
<id column="id" property="id" javaType="java.lang.Integer"/>
<result column="userName" property="userName" javaType="java.lang.String"/>
<result column="birthday" property="birthday" javaType="java.util.Date"/>
<result column="sex" property="sex" javaType="java.lang.String"/>
<result column="address" property="address" javaType="java.lang.String"/>
<!-- 用户与账户一对一映射 -->
<association column="id" property="accountDO" javaType="zw.mybatis.bean.domain.AccountDO" fetchType="lazy" select="zw.mybatis.mapper.AccountMapper.findAccountInformationByUserId"></association>
</resultMap>
<!-- 查询用户信息,根据用户编号查询用户信息及其账户信息,实现账户信息查询的延迟加载 -->
<select id="findUserInformationAndAccountByUserId" parameterType="java.lang.Integer" resultMap="userVOResultMap">
select
id id,
username userName,
birthday birthday,
sex sex,
address address
from
user
where id = #{userId}
</select>
</mapper>
10. 用户持久层测试类
package zw.mybatis.mapper;
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.Test;
import zw.mybatis.bean.vo.UserVO;
import java.io.IOException;
import java.io.InputStream;
/**
* @className UserMapperTest
* @description 用户持久层测试类
* @author 周威
* @date 2020-07-31 14:27
**/
public class UserMapperTest
{
@Test
public void findUserInformationAndRoleByUserIdTest()
{
InputStream is = null;
SqlSession sqlSession = null;
try
{
// 读取配置文件
is = Resources.getResourceAsStream("mybatis/mybatis.xml");
// 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 获取SqlSessionFactory对象
SqlSessionFactory factory = builder.build(is);
// 获取SqlSession对象
sqlSession = factory.openSession();
// 获取代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 查询数据记录
UserVO userVO = userMapper.findUserInformationAndAccountByUserId(1);
// 打印用户信息
System.out.println("---------------用户信息---------------");
System.out.println("用户编号:" + userVO.getId());
System.out.println("用户姓名:" + userVO.getUserName());
System.out.println("用户生日:" + userVO.getBirthday());
System.out.println("用户性别:" + userVO.getSex());
System.out.println("用户住址:" + userVO.getAddress());
// 打印账户信息
System.out.println("---------------角色信息---------------");
System.out.println("账户编号:" + userVO.getAccountDO().getId());
System.out.println("用户编号:" + userVO.getAccountDO().getUserId());
System.out.println("账户金额:" + userVO.getAccountDO().getMoney());
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
// 关闭资源
if(sqlSession != null)
sqlSession.close();
if(is != null)
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}