一、概述
1、延迟加载:
- 就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载
2、好处:
- 先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
3、坏处:
- 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。
4、MyBatis 多表查询
在多表查询时,使用了resultMap
来实现一对一,一对多,多对多关系的操作。主要是通过 association
、collection
实现一对一及一对多映射。association
、collection
具备延迟加载功能。
二、association 延迟加载、collection 延迟加载
association : 用于一对多(一个用户对应多个账号:User ——> Account)
collection :用于多对一
第一步:封装对数据库映射的实体类 User.java、Account.java
package cn.lemon.domain;import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;public class User implements Serializable {
private Integer id;private Date birthday;private String username;private String sex;private String address;private List<Account> accountList = new ArrayList<>();public Integer getId() {
return id;}public void setId(Integer id) {
this.id = id;}public Date getBirthday() {
return birthday;}public void setBirthday(Date birthday) {
this.birthday = birthday;}public String getUsername() {
return username;}public void setUsername(String username) {
this.username = username;}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> getAccountList() {
return accountList;}public void setAccountList(List<Account> accountList) {
this.accountList = accountList;}@Overridepublic String toString() {
return "User{" +"id=" + id +", birthday=" + birthday +", username='" + username + '\'' +", sex='" + sex + '\'' +", address='" + address + '\'' +'}';}
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
package cn.lemon.domain;import java.io.Serializable;public class Account implements Serializable {
private Integer id;private Integer uid;private Double money;private 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;}@Overridepublic String toString() {
return "Account{" +"id=" + id +", uid=" + uid +", money=" + money +'}';}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
第二步:新建持久层(dao)接口 IUserDao.java 、IAccountDao.java,操作数据库
package cn.lemon.dao;import cn.lemon.domain.User;import java.util.List;public interface IUserDao {
public User findById(Integer userId);public List<User> findAll();
}
1234567891011
package cn.lemon.dao;import cn.lemon.domain.Account;import java.util.List;public interface IAccountDao {
public List<Account> findAll();
}
123456789
第三步:新建配置文件 SqlMapConfig.xml (配置懒加载)和 jdbcConfig.properties
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--mybatis配置文件-->
<configuration><!--配置属性或使用属性文件--><properties resource="jdbc.properties"/><!--全局属性配置--><settings><!--开启Mybatis支持延迟加载--><setting name="lazyLoadingEnabled" value="true"/><!--关闭积极延迟加载:任何属性都会引起延迟加载--><setting name="aggressiveLazyLoading" value="false"></setting></settings><!--给包定义别名--><typeAliases><!--定义单个别名--><!--<typeAlias type="com.lxs.domain.User" alias="user"></typeAlias>--><!--配置包定义别名,别名=包中的类的名字(首字母大写小写都可以)--><package name="cn.lemon.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><!--配置单个映射文件--><!--<mapper resource="com/lxs/dao/IUserDao.xml"></mapper>--><package name="cn.lemon.dao"/></mappers>
</configuration>
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///db_mybatis
username=root
password=lemon
1234
第四步:编写持久层接口的映射文件 IUserDao.xml、IAccountDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.lemon.dao.IUserDao"><select id="findById" resultType="user" parameterType="int">SELECT * FROM user WHERE id = #{uid}</select><select id="findAll" resultMap="userMap">SELECT * FROM user</select><resultMap id="userMap" type="user"><id column="id" property="id"></id><!--collection:映射一对多的一的一方(主表方)的集合属性ofType:集合的元素类型,可以写别名select: 查询关联集合的select语句column:查询关联集合的语句的参数--><collection property="accountList" ofType="Account" select="cn.lemon.dao.IAccountDao.findByUid" column="id"><id column="id" property="id"/></collection></resultMap>
</mapper>
12345678910111213141516171819202122232425
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.lemon.dao.IAccountDao"><select id="findAll" resultMap="accountMap">select * from account</select><resultMap id="accountMap" type="account"><id column="id" property="id"/><!--字段名等于属性名可以省略--><result column="uid" property="uid"/><!--<result property="money" column="money"></result>--><!--association映射多对一,多的一方的实体属性* select: 调用select映射的语句查询关联的user数据* column: 调用select映射的语句的输入参数--><association property="user" javaType="user" select="cn.lemon.dao.IUserDao.findById" column="uid"><!--主键不能省略--><id column="id" property="id"/><!-- 同名属性可以省略 --><result property="username" column="username"/><!--<result property="birthday" column="birthday"></result>--><!--<result property="sex" column="sex"></result>--><!--<result property="address" column="address"></result>--></association></resultMap><select id="findByUid" resultType="Account" parameterType="int">SELECT * FROM account WHERE uid= #{aid}</select>
</mapper>
123456789101112131415161718192021222324252627282930313233
第五步:测试类
package cn.lemon.dao;import cn.lemon.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.InputStream;
import java.util.List;public class IUserDaoTest {
private InputStream inputStream;private SqlSessionFactory sqlSessionFactory;private SqlSession sqlSession;private IUserDao iUserDao;@Beforepublic void init() throws Exception {
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);sqlSession = sqlSessionFactory.openSession(true);iUserDao = sqlSession.getMapper(IUserDao.class);}@Testpublic void findById() {
}@Testpublic void findAll() {
List<User> userList = iUserDao.findAll();for (User user : userList) {
System.out.println(user);System.out.println("====================================================================");}System.out.println("-------------------------------------------------------------------------");System.out.println("第一个用户的账户" + userList.get(0).getAccountList());}@Afterpublic void destory() throws Exception {
sqlSession.close();inputStream.close();}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
package cn.lemon.dao;import cn.lemon.domain.Account;
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.InputStream;
import java.util.List;import static org.junit.Assert.*;public class IAccountDaoTest {
private InputStream inputStream;private SqlSessionFactory sqlSessionFactory;private SqlSession sqlSession;private IAccountDao iAccountDao;@Beforepublic void init() throws Exception {
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);sqlSession = sqlSessionFactory.openSession(true);iAccountDao = sqlSession.getMapper(IAccountDao.class);}@Testpublic void findAll() {
List<Account> accountList = iAccountDao.findAll();for (Account account : accountList) {
System.out.println(account);System.out.println("--------------------------------------------------------------------------------");}System.out.println("***************************************************************************");System.out.println("第一个账户的用户为:" + accountList.get(0).getUser());//当使用用户时才查询用户,称为懒加载}@Afterpublic void destory() throws Exception {
sqlSession.close();inputStream.close();}
}