简介
通过前面的学习,我们已经掌握了Mybatis中一对一,一对多,多对多关系的配置及实现,可以实现对象的 关联查询。实际开发过程中很多时候我们并不需要总是在加载用户信息时就一定要加载他的账户信息。此时就是我们所说的延迟加载。
延迟加载
延迟加载(懒加载)就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。
优点
先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张速度要快。 坏处
因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。
目录结构
src
main
java
cn.water.dao
AccountDao.java (持久层接口)UserDao.java (持久层接口) cn.water.domain
Account.java (实体类)User.java (实体类) resources
cn.water.dao
AccountDao.xml (映射配置文件)UserDao.xml (映射配置文件) SqlMapConfig.xml (MyBatis主配置文件)jdbcConfig.properties (数据库连接信息文件) test
MyBatis主配置文件
SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
< configuration>
< properties resource = " jdbcConfig.properties" > </ properties>
< typeAliases>
< package name = " cn.water.domain" />
</ typeAliases>
< environments default = " mysql" >
< environment id = " mysql" >
< transactionManager type = " JDBC" > </ transactionManager>
< dataSource type = " POOLED" >
< property name = " driver" value = " ${jdbc.driver}" />
< property name = " url" value = " ${jdbc.url}" />
< property name = " username" value = " ${jdbc.username}" />
< property name = " password" value = " ${jdbc.password}" />
</ dataSource>
</ environment>
</ environments>
< mappers>
< package name = " cn.water.dao" />
</ mappers>
</ configuration>
数据库连接信息文件
jdbcConfig.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
实体类
Account.java
package cn. water. domain;
public class Account {
private Integer id;
private Integer uid;
private Double money;
private User user;
@Override
public String toString ( ) {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
", 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;
}
public User getUser ( ) {
return user;
}
public void setUser ( User user) {
this . user = user;
}
}
User.java
package cn. water. domain;
import java. util. Date;
import java. util. List;
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List< Account> accounts;
@Override
public String toString ( ) {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
", 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 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;
}
public List< Account> getAccounts ( ) {
return accounts;
}
public void setAccounts ( List< Account> accounts) {
this . accounts = accounts;
}
}
持久层接口
AccountDao.java
package cn. water. dao;
import cn. water. domain. Account;
import java. util. List;
public interface AccountDao {
List< Account> findAll ( ) ;
List< Account> findById ( Integer id) ;
}
UserDao.java
package cn. water. dao;
import cn. water. domain. Account;
import cn. water. domain. User;
import java. util. List;
public interface UserDao {
User findById ( Integer id) ;
List< User> findAll ( ) ;
}
映射配置文件
AccountDao.xml
<?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 = " cn.water.dao.AccountDao" >
< resultMap id = " o2o" type = " account" >
< id column = " id" property = " id" />
< result column = " uid" property = " uid" />
< result column = " money" property = " money" />
< association
property = " user"
javaType = " user"
select = " cn.water.dao.UserDao.findById"
column = " uid"
>
</ association>
</ resultMap>
< select id = " findAll" resultMap = " o2o" >
SELECT * FROM account
</ select>
< select id = " findById" parameterType = " INT" resultType = " account" >
SELECT * FROM account WHERE uid = #{id}
</ select>
</ mapper>
UserDao.xml
<?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 = " cn.water.dao.UserDao" >
< select id = " findById" parameterType = " INT" resultType = " user" >
SELECT * FROM user WHERE id = #{uid}
</ select>
< resultMap id = " o2m" type = " user" >
< id column = " id" property = " id" />
< result column = " username" property = " username" />
< result column = " birthday" property = " birthday" />
< result column = " sex" property = " sex" />
< result column = " address" property = " address" />
< collection
property = " accounts"
ofType = " account"
select = " cn.water.dao.AccountDao.findById"
column = " id"
>
</ collection>
</ resultMap>
< select id = " findAll" resultMap = " o2m" >
SELECT * FROM user
</ select>
</ mapper>
测试类
MyBatisTest.java
package cn. water;
import cn. water. dao. AccountDao;
import cn. water. dao. UserDao;
import cn. water. domain. Account;
import cn. water. 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;
public class MyBatisTest {
private InputStream inputStream;
private SqlSession session;
@Before
public void init ( ) throws IOException {
inputStream = Resources. getResourceAsStream ( "SqlMapConfig.xml" ) ;
SqlSessionFactory factory = new SqlSessionFactoryBuilder ( ) . build ( inputStream) ;
session = factory. openSession ( true ) ;
}
@After
public void destroy ( ) throws IOException {
session. close ( ) ;
inputStream. close ( ) ;
}
@Test
public void test01 ( ) {
AccountDao dao = session. getMapper ( AccountDao. class ) ;
for ( Account account : dao. findAll ( ) ) {
System. out. println ( account) ;
}
}
@Test
public void test02 ( ) {
UserDao dao = session. getMapper ( UserDao. class ) ;
for ( User user : dao. findAll ( ) ) {
System. out. println ( user) ;
}
}
}
一对一查询(延迟)
一对一查询:从查询 账户信息(Account) 出发,关联查询 用户信息(User)
立即加载:一次多表查询
SELECT u.*,a.* FROM user u,account a WHERE u.id = a.uid; 延迟加载:多次单表查询(提供关联信息)
SELECT * FROM account;(获取uid) SELECT * FROM user WHERE id = #{uid}; (提供uid)
Account 实体类
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
private User user;
}
User 实体类
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
}
Account 持久层接口
List< Account> findAll ( ) ;
User 持久层接口
User findById ( Integer id) ;
Account 映射配置文件
< resultMap id = " o2o" type = " account" >
< id column = " id" property = " id" />
< result column = " uid" property = " uid" />
< result column = " money" property = " money" />
< association
property = " user"
javaType = " user"
select = " cn.water.dao.UserDao.findById"
column = " uid"
>
</ association>
</ resultMap>
< select id = " findAll" resultMap = " o2o" >
SELECT * FROM account
</ select>
User 映射配置文件
< select id = " findById" parameterType = " INT" resultType = " user" >
SELECT * FROM user WHERE id = #{uid}
</ select>
测试类
@Test
public void test01 ( ) {
AccountDao dao = session. getMapper ( AccountDao. class ) ;
for ( Account account : dao. findAll ( ) ) {
System. out. println ( account) ;
}
}
运行结果
一对多查询(延迟)
一对多查询:从查询 用户信息(User) 出发,关联查询 账户信息(Account)
立即加载:一次多表查询
SELECT * FROM user u LEFT OUTER JOIN account a ON u.id = a.uid; 延迟加载:多次单表查询(通过关联信息)
SELECT * FROM user;(获取id) SELECT * FROM account WHERE uid = #{id}(提供id)
User 实体类
将 账户类(Account) 的List集合 设置为变量
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List< Account> accounts;
}
Account 实体类
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
}
User 持久层接口
List< User> findAll ( ) ;
Account 持久层接口
返回值 对应 User类的List<Account>变量
List< Account> findById ( Integer id) ;
User 映射配置文件
< resultMap id = " o2m" type = " user" >
< id column = " id" property = " id" />
< result column = " username" property = " username" />
< result column = " birthday" property = " birthday" />
< result column = " sex" property = " sex" />
< result column = " address" property = " address" />
< collection
property = " accounts"
ofType = " account"
select = " cn.water.dao.AccountDao.findById"
column = " id"
>
</ collection>
</ resultMap>
< select id = " findAll" resultMap = " o2m" >
SELECT * FROM user
</ select>
Account 映射配置文件
< select id = " findById" parameterType = " INT" resultType = " account" >
SELECT * FROM account WHERE uid = #{id}
</ select>
测试类
@Test
public void test02 ( ) {
UserDao dao = session. getMapper ( UserDao. class ) ;
for ( User user : dao. findAll ( ) ) {
System. out. println ( user) ;
}
}
运行结果