Mybatis的延迟加载和立即加载
Mybatis的延迟加载和立即加载
示例:在一对多中,当我们有一个用户,他有100个帐户
问题1:在查询用户时,要不要把关联的账户查出来?
问题2:在查询账户时,要不要把关联的用户信息查出来?
问题1:在查询用户时,要不要把关联的账户查出来?
用户和帐户之间的关系应该是一对多的关系,一个用户对应多个账户,如果在查询用户时,同时查询到他关联的帐户,那么这些查询到的账户信息就会占据很大的内存,所以应该是是么时候使用,是么时候才查询帐户信息。
问题2:在查询账户时,要不要把关联的用户信息查出来?
帐户和用户之间的关系应该是一对一的,一个帐户应该对应一个用户,如果查询账户时,账户的所属用户信息应该是随着一起查询出来的,且用户信息占据内存很小。
延迟加载:(应用于一对多,多对多,即关联的对象为“多”时)
在真正使用数据时才发起查询,不用的时候不查询,按需加载(懒加载)。
立即加载:(应用于多对一,一对一,即关联的对象为“一”时)
不管用不用,在调用方法的时候就立即执行,马上发起查询。
一对一实现延迟:account-user 的一对一延迟加载
帐户account实体类
package com.itheima.domain;
import java.io.Serializable;
/**
* @Author: lijiahao
* @Description:
* @Data: Create in 12:23 2020/2/26
* @Modified By:
*/
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 +
'}';
}
}
user的接口
package com.itheima.dao;
import com.itheima.domain.User;
import java.util.List;
/**
* @Author: lijiahao
* @Description: 用户的持久层接口
* @Data: Create in 21:42 2020/2/22
* @Modified By:
*/
public interface IUserDao {
//查询所有用户,同时获取到用户下所有账户的信息
List<User> findAll();
//根据id查询用户信息
User findById(Integer userId);
}
主配置文件
<?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">
<!--mybatis的主配置文件-->
<configuration>
<!--配置连接池-->
<properties resource="jdbcConfig.properties"/>
<!--配置参数-->
<settings>
<!--开启mybatis延迟加载,默认为false-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--开启立即加载,mybatis3.4.1以上默认为false-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!--配置别名 类名就是别名,不区分大小写-->
<typeAliases>
<package name="com.itheima.domain" ></package>
</typeAliases>
<!--配置环境-->
<environments default="mysql">
<!--配置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>
<!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
<mappers>
<package name="com.itheima.dao"></package>
</mappers>
</configuration>
帐户映射配置文件IAccountDao.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="com.itheima.dao.IAccountDao">
<!--定义封装account和user的ResultMap account为主表,user为从表,实现一对一-->
<resultMap id="accountUserMap" type="account">
<!--主键配置,property为属性名,column为数据库列名(sql语句起了别名as后面的,下方sql语句可以搜索到的)-->
<!--aid为-->
<id property="id" column="id"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!--一对一的关系映射,配置封装user的内容
select属性指定的内容:查询用户的唯一标识
column属性指定的内容:用户根据id查询时,所需要的参数的值-->
<association property="user" column="uid" javaType="user" select="com.itheima.dao.IUserDao.findById">
</association>
</resultMap>
<!--查询所有-->
<select id="findAll" resultMap="accountUserMap">
select * from account
</select>
</mapper>
测试类
package com.itheima;
import com.itheima.dao.IAccountDao;
import com.itheima.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.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @Author: lijiahao
* @Description:
* @Data: Create in 22:56 2020/2/22
* @Modified By:
*/
public class AccountTest {
private InputStream in;
private SqlSession sqlSession;
private IAccountDao accountDao;
@Before
public void init() throws IOException {
//1.读取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
sqlSession = sqlSessionFactory.openSession(true);
//3.使用工厂生产dao对象
accountDao = sqlSession.getMapper(IAccountDao.class);
}
@After
public void destory() throws IOException {
in.close();
}
@Test
public void testFindAll() throws IOException {
//5.使用代理对象执行方法
List<Account> accounts = accountDao.findAll();
for (Account account : accounts) {
System.out.println(account);
System.out.println(account.getUser());
}
}
}
一对多实现延迟加载:user-account 的一对多的延迟加载
用户user实体类
package com.itheima.domain;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @Author: lijiahao
* @Description:
* @Data: Create in 21:37 2020/2/22
* @Modified By:
*/
public class User implements Serializable {
private Integer 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 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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
account的接口
package com.itheima.dao;
import com.itheima.domain.Account;
import java.util.List;
/**
* @Author: lijiahao
* @Description:
* @Data: Create in 12:25 2020/2/26
* @Modified By:
*/
public interface IAccountDao {
/**
* @Author Lijiahao
* @Description 查询所有账户, 同时还要获取到当前账户的所有信息
* @Date 16:32 2020/2/26
* @Param []
* @return java.util.List<com.itheima.domain.Account>
**/
List<Account> findAll();
//根据用户id查询帐户信息
List<Account> findAccountByUid(Integer uid);
}
主配置文件
package com.itheima.domain;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @Author: lijiahao
* @Description:
* @Data: Create in 21:37 2020/2/22
* @Modified By:
*/
public class User implements Serializable {
private Integer 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 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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
用户映射配置文件IUserDao.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="com.itheima.dao.IUserDao">
<!--定义user的resultMap user为主表,account为从表,构成一对多关系-->
<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集合的映射
select 后面即为延迟 后的查询语句,根据user中的id查询-->
<collection property="accounts" ofType="account" select="com.itheima.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 = #{userid}
</select>
</mapper>
测试类
package com.itheima;
import com.itheima.dao.IUserDao;
import com.itheima.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;
/**
* @Author: lijiahao
* @Description:
* @Data: Create in 22:56 2020/2/22
* @Modified By:
*/
public class UserTest {
private InputStream in;
private SqlSession sqlSession;
private IUserDao userDao;
@Before
public void init() throws IOException {
//1.读取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
sqlSession = sqlSessionFactory.openSession(true);
//3.使用工厂生产dao对象
userDao = sqlSession.getMapper(IUserDao.class);
}
@After
public void destory() throws IOException {
in.close();
}
@Test
public void testFindAll() throws IOException {
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
System.out.println(user.getAccounts());
}
}
}
Mybatis的延迟加载和立即加载的更多相关文章
- Mybatis源码解析(二) —— 加载 Configuration
Mybatis源码解析(二) -- 加载 Configuration 正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...
- Hibernate之加载策略(延迟加载与即时加载)和抓取策略(fetch)
假设现在有Book和Category两张表,表的关系为双向的一对多,表结构如下: 假设现在我想查询id为2的那本书的书名,使用session.get(...)方法: Session session=H ...
- EF如何操作内存中的数据以及加载相关联表的数据:延迟加载、贪婪加载、显示加载
之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需要用的,这个系列讲讲如何使用EF操作数据库.老版本的EF主要是通过Ob ...
- EF 延迟加载和预先加载
最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精 本节探讨延迟加载和预先加载 Entity Frame ...
- Entity Framework关联查询以及数据加载(延迟加载,预加载)
数据加载分为延迟加载和预加载 EF的关联实体加载有三种方式:Lazy Loading,Eager Loading,Explicit Loading,其中Lazy Loading和Explicit Lo ...
- EF如何操作内存中的数据和加载外键数据:延迟加载、贪婪加载、显示加载
EF如何操作内存中的数据和加载外键数据:延迟加载.贪婪加载.显示加载 之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需 ...
- 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性)
一. 简介 上一个章节中,也介绍了立即加载和延迟加载,但上一个章节是针对单表而言的,不含外键,立即也好,延迟也好,都是指单表中的数据.但本章节重点介绍的三种加载方式均是针对含(导航属性.外键)的情况下 ...
- ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪
ASP.NET MVC深入浅出(被替换) 一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...
- NHibernate 延迟加载与立即加载 (第七篇)
NHibernate 延迟加载与立即加载 (第七篇) 一.延迟加载 延迟加载可以理解为:当需要用的时候才加载. 假设我们数据库有一个Person对象,一个Country对象,其中Person属于Cou ...
随机推荐
- linux下的 $ ./configure $ sudo make && sudo make install
$ ./configure $ sudo make && sudo make install 1)./configure命令就是执行当前目录的名为configure的脚本,主要的作用是 ...
- PS-蒙版的深入解析
ps四大核心技术是什么?通道.蒙版.路径.选区 通道: 通道的详解,不过比较早的文章了. http://www.blueidea.com/tech/graph/2004/2056.asp PS通道快速 ...
- GORM入门指南
gorm是一个使用Go语言编写的ORM框架.它文档齐全,对开发者友好,支持主流数据库. gorm介绍 Github GORM 中文官方网站内含十分齐全的中文文档,有了它你甚至不需要再继续向下阅读本文. ...
- Java线程核心基础(上)
Java线程核心基础(上) 一.实现多线程 根据Oracle官方文档,目前推荐的创建线程方法主要有两种,分别是继承Thread类和实现Runnable接口.通过阅读Thread类源码,可以发现二者不同 ...
- Thingsboard源码安装部署
交流QQ群 如果安装有其他问题,可以到QQ群求助 环境安装 开发环境要求:Jdk 1.8版本Postgresql 9以上Node.jsNpmMaven 3.6以上Git工具Idea开发工具 JDK 下 ...
- Python socket 基础(Server) - Foundations of Python Socket
Python socket 基础 Server - Foundations of Python Socket 通过 python socket 模块建立一个提供 TCP 链接服务的 server 可分 ...
- 卫星轨道相关笔记SGP4
由卫星历书确定卫星轨道状态向量 卫星历书的表示方法有2种: TLE(Two Line Element),和轨道根数表示方法 由卫星历书计算出卫星轨道状态向量的方法有2种: SGP方法,NORAD的方法 ...
- Windows下无法颜色转义
只需在最前面添加 import os os.system("") 参考文献:https://blog.csdn.net/ytzlln/article/details/8194524 ...
- MongoDB oplog 详解
oplog 简介 oplog 是local库下的一个固定集合,Secondary就是通过查看Primary的oplog这个集合来进行复制的.每个节点都有oplog,记录从主节点复制过来的信息,这样每个 ...
- [Linux]命令返回值以及错误对照表
Linux执行完命令之后默认会有一个返回值 # ls app backupconfig.json Doc manage.py __pycache__ settings.py # echo $? 0 错 ...