mybatis延迟加载、缓存

打印 上一主题 下一主题

主题 1036|帖子 1036|积分 3108

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目次
一、所需表
二、延迟加载
1.延迟加载概念
2.立刻加载和延迟加载的应用场景
3.多对一延迟加载查询演示
(1)实体类
User
Account
(2)AccountMapper接口
(3)AccountMapper.xml
(4)UserMapper接口
(5)UserMapper.xml
(6)在总配置文件(mybatis-config.xml)中开启延迟加载配置
(7)测试类
(8)运行
(9)如果测试类中的输出语句改为
4.一对多延迟加载
(1)实体类
(2)UserMapper接口
(3)UserMapper.xml文件
(4)AccountMapper接口
(5)AccountMapper.xml文件
(6)在总配置文件中开启延迟加载
(7)测试类
(8)运行
三、mybatis框架的缓存
1.概念
2.一级缓存
(1)验证一级缓存的存在
测试类
运行
(2)一级缓存失效的四种情况
①使用差别的sqlSession对象查询
测试类
运行
②使用相同的sqlSession对象进行查询,但是查询条件差别
测试类
 运行
③使用相同的sqlSession对象进行查询,但是在两次实验中间我们进行了一次增删改操作
UserMapper接口
UserMapper.xml
测试类
运行
④使用相同的sqlSession对象进行查询,但是手动清除了缓存
测试类
运行
3.二级缓存
(1)在总配置文件中开启二级缓存
(2)在映射配置文件中配置
(3)实体类实现序列化接口
(4)二级缓存必须在SqlSession关闭或提交之后
(5)证实二级缓存
测试类
运行:


一、所需表

account


user


二、延迟加载

1.延迟加载概念

立刻加载:当前查询用户的时间,默认把该用户所拥有的账户信息查询出来了
延迟加载:当前查询用户的时间,没有把该用户所拥有的账户信息查询出来,而是使用账户数据的时间,再去查询账户的数据

2.立刻加载和延迟加载的应用场景

(1)查询账户的时间,可以直接把用户查询出来(多对一),这个时间可以选择立刻加载
(2)查询用户的时间,可以先不查账户信息,需要账户信息的时间再去查,这时选择延迟加载
3.多对一延迟加载查询演示

(1)实体类

User

  1. package com.qcby.pojo;
  2. import java.util.Date;
  3. /*
  4. * 一
  5. * */
  6. public class User {
  7.     private Integer id;
  8.     private String username;
  9.     private Date birthday;
  10.     private String sex;
  11.     private String address;
  12.     public User() {
  13.     }
  14.     public User(Integer id, String username, Date birthday, String sex, String address) {
  15.         this.id = id;
  16.         this.username = username;
  17.         this.birthday = birthday;
  18.         this.sex = sex;
  19.         this.address = address;
  20.     }
  21.     public Integer getId() {
  22.         return id;
  23.     }
  24.     public void setId(Integer id) {
  25.         this.id = id;
  26.     }
  27.     public String getUsername() {
  28.         return username;
  29.     }
  30.     public void setUsername(String username) {
  31.         this.username = username;
  32.     }
  33.     public Date getBirthday() {
  34.         return birthday;
  35.     }
  36.     public void setBirthday(Date birthday) {
  37.         this.birthday = birthday;
  38.     }
  39.     public String getSex() {
  40.         return sex;
  41.     }
  42.     public void setSex(String sex) {
  43.         this.sex = sex;
  44.     }
  45.     public String getAddress() {
  46.         return address;
  47.     }
  48.     public void setAddress(String address) {
  49.         this.address = address;
  50.     }
  51.     @Override
  52.     public String toString() {
  53.         return "User{" +
  54.                 "id=" + id +
  55.                 ", username='" + username + '\'' +
  56.                 ", birthday=" + birthday +
  57.                 ", sex='" + sex + '\'' +
  58.                 ", address='" + address + '\'' +
  59.                 '}';
  60.     }
  61. }
复制代码
Account

  1. package com.qcby.pojo;
  2. /*
  3. * 多
  4. * */
  5. public class Account {
  6.     private Integer id;
  7.     private String money;
  8.     private Integer uid;
  9.     //多对一
  10.     private User user;
  11.     public Account() {
  12.     }
  13.     public Account(Integer id, String money, Integer uid, User user) {
  14.         this.id = id;
  15.         this.money = money;
  16.         this.uid = uid;
  17.         this.user = user;
  18.     }
  19.     public Integer getUid() {
  20.         return uid;
  21.     }
  22.     public void setUid(Integer uid) {
  23.         this.uid = uid;
  24.     }
  25.     public User getUser() {
  26.         return user;
  27.     }
  28.     public void setUser(User user) {
  29.         this.user = user;
  30.     }
  31.     public Integer getId() {
  32.         return id;
  33.     }
  34.     public void setId(Integer id) {
  35.         this.id = id;
  36.     }
  37.     public String getMoney() {
  38.         return money;
  39.     }
  40.     public void setMoney(String money) {
  41.         this.money = money;
  42.     }
  43.     @Override
  44.     public String toString() {
  45.         return "Account{" +
  46.                 "id=" + id +
  47.                 ", money='" + money + '\'' +
  48.                 ", uid=" + uid +
  49.                 ", user=" + user +
  50.                 '}';
  51.     }
  52. }
复制代码
(2)AccountMapper接口

  1. package com.qcby.mapper;
  2. import com.qcby.pojo.Account;
  3. import java.util.List;
  4. public interface AccountMapper {
  5.    
  6.     /*
  7.     * 多对一:
  8.     * 查询所有
  9.     * */
  10.     public List<Account> findAll();
  11. }
复制代码
(3)AccountMapper.xml

在 <association> 标签中,需要指定一个 column 属性,这个属性的值应该是 account 表中用来关联 user 表的外键列名: column="uid"
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3.         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4.         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.qcby.mapper.AccountMapper"> <!--对谁进行操作就写谁-->
  6.     <!--多对一:-->
  7.     <!--查询所有:public List<Account> findAll();-->
  8.     <select id="findAll" resultMap="accountMap">
  9.         select * from account
  10.     </select>
  11.     <resultMap id="accountMap" type="account">
  12.         <id property="id" column="id"/>
  13.         <result property="money" column="money"/>
  14.         <result property="uid" column="uid"/>
  15.         <!--配置延迟加载-->
  16.         <association property="user" column="uid" javaType="user" select="com.qcby.mapper.UserMapper.findById">
  17.             <id column="id" property="uid"/>
  18.             <result column="username" property="username"/>
  19.             <result column="birthday" property="birthday"/>
  20.             <result column="sex" property="sex"/>
  21.             <result column="address" property="address"/>
  22.         </association>
  23.     </resultMap>
  24. </mapper>
复制代码
(4)UserMapper接口

  1. package com.qcby.mapper;
  2. import com.qcby.pojo.User;
  3. public interface UserMapper {
  4.    
  5.     /*
  6.     * 多对一:
  7.     * 根据id查询
  8.     * */
  9.     public User findById(Integer id);
  10. }
复制代码
(5)UserMapper.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3.         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4.         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.qcby.mapper.UserMapper"> <!--对谁进行操作就写谁-->
  6.     <!--多对一-->
  7.     <!--根据id查询:public User findById(Integer id);-->
  8.     <select id="findById" parameterType="int" resultType="user">
  9.         select * from user where id=#{id}
  10.     </select>
  11. </mapper>
复制代码
(6)在总配置文件(mybatis-config.xml)中开启延迟加载配置

mybatis-config.xml
  1. <settings>
  2.     <!--开启延迟加载-->
  3.     <setting name="lazyLoadingEnabled" value="true"/>
  4.     <!--将积极加载改为消极加载及按需加载-->
  5.     <setting name="aggressiveLazyLoading" value="false"/>
  6. </settings>
复制代码
(7)测试类

  1. package com.qcby.test;
  2. import com.qcby.mapper.AccountMapper;
  3. import com.qcby.mapper.UserMapper;
  4. import com.qcby.pojo.Account;
  5. import com.qcby.pojo.User;
  6. import org.apache.ibatis.io.Resources;
  7. import org.apache.ibatis.session.SqlSession;
  8. import org.apache.ibatis.session.SqlSessionFactory;
  9. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  10. import org.junit.After;
  11. import org.junit.Before;
  12. import org.junit.Test;
  13. import java.io.IOException;
  14. import java.io.InputStream;
  15. import java.util.ArrayList;
  16. import java.util.List;
  17. public class demo {
  18.     private InputStream inputStream;
  19.     private SqlSession sqlSession;
  20.     private AccountMapper accountMapper;
  21.     private UserMapper userMapper;
  22.     @Before
  23.     public void init() throws IOException {
  24.         //加载配置文件
  25.         inputStream= Resources.getResourceAsStream("mybatis-config.xml");
  26.         //创建工厂对象
  27.         SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
  28.         //创建session对象
  29.         sqlSession=sqlSessionFactory.openSession();
  30.         //获取到代理对象
  31.         userMapper=sqlSession.getMapper(UserMapper.class);
  32.         accountMapper=sqlSession.getMapper(AccountMapper.class);
  33.     }
  34.     /*
  35.     * 多对一:
  36.     * account查询所有
  37.     * */
  38.     @Test
  39.     public void findAllTest(){
  40.         List<Account> accounts=accountMapper.findAll();
  41.         for (Account account:accounts){
  42.             //System.out.println("开始...");
  43.             System.out.println(account.getMoney());
  44.             //System.out.println("结束...");
  45.             System.out.println("--------------------");
  46.         }
  47.     }
  48.     @After
  49.     public void destory() throws IOException {
  50.         inputStream.close();
  51.         sqlSession.close();
  52.     }
  53. }
复制代码
(8)运行


可以看到此时是没有加载出来用户的信息的
(9)如果测试类中的输出语句改为

System.out.println(account.getUser().getUsername());
再运行:

可以看到此时实验了user根据id查询的sql语句
4.一对多延迟加载

(1)实体类

User类
  1. package com.qcby.pojo;
  2. import java.util.Date;
  3. import java.util.List;
  4. /*
  5. * 一
  6. * */
  7. public class User {
  8.     private Integer id;
  9.     private String username;
  10.     private Date birthday;
  11.     private String sex;
  12.     private String address;
  13.    
  14.     /*一对多*/
  15.     private List<Account> accounts;
  16.     public List<Account> getAccounts() {
  17.         return accounts;
  18.     }
  19.     public void setAccounts(List<Account> accounts) {
  20.         this.accounts = accounts;
  21.     }
  22.     public Integer getId() {
  23.         return id;
  24.     }
  25.     public void setId(Integer id) {
  26.         this.id = id;
  27.     }
  28.     public String getUsername() {
  29.         return username;
  30.     }
  31.     public void setUsername(String username) {
  32.         this.username = username;
  33.     }
  34.     public Date getBirthday() {
  35.         return birthday;
  36.     }
  37.     public void setBirthday(Date birthday) {
  38.         this.birthday = birthday;
  39.     }
  40.     public String getSex() {
  41.         return sex;
  42.     }
  43.     public void setSex(String sex) {
  44.         this.sex = sex;
  45.     }
  46.     public String getAddress() {
  47.         return address;
  48.     }
  49.     public void setAddress(String address) {
  50.         this.address = address;
  51.     }
  52.     @Override
  53.     public String toString() {
  54.         return "User{" +
  55.                 "id=" + id +
  56.                 ", username='" + username + '\'' +
  57.                 ", birthday=" + birthday +
  58.                 ", sex='" + sex + '\'' +
  59.                 ", address='" + address + '\'' +
  60.                 ", accounts=" + accounts +
  61.                 '}';
  62.     }
  63. }
复制代码
(2)UserMapper接口

  1. /*
  2. * 一对多:
  3. * 查询所有
  4. * */
  5. public List<User> findUserAll();
复制代码
(3)UserMapper.xml文件

  1. <!--一对多-->
  2. <!--查询所有:public List<User> findUserAll();-->
  3. <select id="findUserAll" resultMap="userMap">
  4.     select * from user
  5. </select>
  6. <resultMap id="userMap" type="user">
  7.     <id property="id" column="id"/>
  8.     <result property="username" column="username"/>
  9.     <result property="birthday" column="birthday"/>
  10.     <result property="sex" column="sex"/>
  11.     <result property="address" column="address"/>
  12.     <collection property="accounts" column="id" ofType="account" select="com.qcby.mapper.AccountMapper.findAccountById">
  13.         <id column="id" property="id"/>
  14.         <result column="money" property="money"/>
  15.         <result column="uid" property="uid"/>
  16.     </collection>
  17. </resultMap>
复制代码
(4)AccountMapper接口

  1. /*
  2. * 一对多:
  3. * 根据id查询
  4. * */
  5. public Account findAccountById(Integer id);
复制代码
(5)AccountMapper.xml文件

  1. <!--一对多-->
  2. <!--根据id查询:public Account findAccountById(Integer id);-->
  3. <select id="findAccountById" parameterType="int" resultType="account">
  4.     select * from account where id=#{id}
  5. </select>
复制代码
(6)在总配置文件中开启延迟加载

  1. <settings>
  2.     <!--开启延迟加载-->
  3.     <setting name="lazyLoadingEnabled" value="true"/>
  4.     <!--将积极加载改为消极加载及按需加载-->
  5.     <setting name="aggressiveLazyLoading" value="false"/>
  6. </settings>
复制代码
(7)测试类

  1. /*
  2. * 一对多:
  3. * user查询所有
  4. * */
  5. @Test
  6. public void findUserAllTest(){
  7.     List<User> users=userMapper.findUserAll();
  8.     for (User user:users){
  9.         System.out.println(user.getUsername()+"  "+user.getAddress());
  10.         System.out.println("--------------------");
  11.     }
  12. }
复制代码
(8)运行



三、mybatis框架的缓存

1.概念

常常需要查询,不需要修改的数据,不特殊紧张的数据都可以存储到缓存中
2.一级缓存

①mybatis的一级缓存是SqlSession的缓存
②查询的时间,先从SqlSession的缓存中查找,如果有,直接返回,如果没有,再去查询数据库
(1)验证一级缓存的存在

查询两次,检察结果
查询的语句在多对一查询的时间写过了
测试类

  1. /*
  2. * 验证一级缓存的存在
  3. * */
  4. @Test
  5. public void findUserByIdTest(){
  6.     User user1=userMapper.findById(1);
  7.     System.out.println(user1);
  8.     User user2=userMapper.findById(1);
  9.     System.out.println(user2);
  10. }
复制代码
运行


(2)一级缓存失效的四种情况

①使用差别的sqlSession对象查询

测试类

  1. package com.qcby.test;
  2. import com.qcby.mapper.AccountMapper;
  3. import com.qcby.mapper.UserMapper;
  4. import com.qcby.pojo.Account;
  5. import com.qcby.pojo.User;
  6. import org.apache.ibatis.io.Resources;
  7. import org.apache.ibatis.session.SqlSession;
  8. import org.apache.ibatis.session.SqlSessionFactory;
  9. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  10. import org.junit.After;
  11. import org.junit.Before;
  12. import org.junit.Test;
  13. import java.io.IOException;
  14. import java.io.InputStream;
  15. import java.util.ArrayList;
  16. import java.util.List;
  17. public class demo {
  18.     private InputStream inputStream;
  19.     private SqlSession sqlSession;
  20.     private SqlSession sqlSession2;
  21.     private AccountMapper accountMapper;
  22.     private UserMapper userMapper;
  23.     private UserMapper userMapper2;
  24.     @Before
  25.     public void init() throws IOException {
  26.         //加载配置文件
  27.         inputStream= Resources.getResourceAsStream("mybatis-config.xml");
  28.         //创建工厂对象
  29.         SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
  30.         //创建session对象
  31.         sqlSession=sqlSessionFactory.openSession();
  32.         sqlSession2=sqlSessionFactory.openSession();
  33.         //获取到代理对象
  34.         userMapper=sqlSession.getMapper(UserMapper.class);
  35.         userMapper2=sqlSession2.getMapper(UserMapper.class);
  36.         accountMapper=sqlSession.getMapper(AccountMapper.class);
  37.     }
  38.     /*
  39.      * 一级缓存失效的四种情况:
  40.      * 1.使用不同的sqlSession对象进行查询
  41.      * */
  42.     @Test
  43.     public void findUserByIdTest1(){
  44.         User user1=userMapper.findById(1);
  45.         System.out.println(user1);
  46.         User user2=userMapper2.findById(1);
  47.         System.out.println(user2);
  48.     }
  49.     @After
  50.     public void destory() throws IOException {
  51.         inputStream.close();
  52.         sqlSession.close();
  53.     }
  54. }
复制代码
运行



②使用相同的sqlSession对象进行查询,但是查询条件差别

测试类

  1. /*
  2. * 一级缓存失效的四种情况:
  3. * 2.使用相同的sqlSession对象进行查询,但是查询条件不同
  4. * */
  5. @Test
  6. public void findUserByIdTest2(){
  7.     User user1=userMapper.findById(1);
  8.     System.out.println(user1);
  9.     User user2=userMapper.findById(2);
  10.     System.out.println(user2);
  11. }
复制代码
 运行


③使用相同的sqlSession对象进行查询,但是在两次实验中间我们进行了一次增删改操作

UserMapper接口

  1. /*
  2. * 根据id删除
  3. * */
  4. public int deleteById(Integer id);
复制代码
UserMapper.xml

  1. <!--根据id删除:public int deleteById(Integer id);-->
  2. <delete id="deleteById" parameterType="int">
  3.     delete from user where id=#{id}
  4. </delete>
复制代码
测试类

  1. /*
  2. * 一级缓存失效的四种情况:
  3. * 3.使用相同的sqlSession对象进行查询,但是在两次执行中间我们进行了一次增删改操作
  4. * */
  5. @Test
  6. public void findUserByIdTest3(){
  7.     User user1= userMapper.findById(1);
  8.     System.out.println(user1);
  9.     userMapper.deleteById(3);
  10.     sqlSession.commit();
  11.     User user2=userMapper.findById(1);
  12.     System.out.println(user2);
  13. }
复制代码
运行


④使用相同的sqlSession对象进行查询,但是手动清除了缓存

测试类

  1. /*
  2. * 一级缓存失效的四种情况:
  3. *  4.使用相同的sqlSession对象进行查询,但是手动清除了缓存
  4. * */
  5. @Test
  6. public void findUserByIdTest4(){
  7.     User user1=userMapper.findById(1);
  8.     System.out.println(user1);
  9.     sqlSession.clearCache();//手动清理缓存
  10.     User user2=userMapper.findById(1);
  11.     System.out.println(user2);
  12. }
复制代码
运行


3.二级缓存

二级缓存是SqlSessionFactory级别的
(1)在总配置文件中开启二级缓存

  1. <!--开启二级缓存-->
  2. <settings>
  3.     <setting name="cacheEnabled" value="true"/>
  4.     <setting name="logImpl" value="STDOUT_LOGGING"/>
  5. </settings>
复制代码
(2)在映射配置文件中配置<cache>


(3)实体类实现序列化接口



(4)二级缓存必须在SqlSession关闭或提交之后

(5)证实二级缓存

二级缓存的适用对象地点差别,但是也从缓存加载,二级缓存存储的是零散数据,是组装出来的对象
测试类

  1. package com.qcby.test;
  2. import com.qcby.mapper.UserMapper;
  3. import com.qcby.pojo.User;
  4. import org.apache.ibatis.io.Resources;
  5. import org.apache.ibatis.session.SqlSession;
  6. import org.apache.ibatis.session.SqlSessionFactory;
  7. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  8. import org.junit.Test;
  9. import java.io.IOException;
  10. import java.io.InputStream;
  11. public class demo2 {
  12.     @Test
  13.     public void test() throws IOException {
  14.         //加载配置文件
  15.         InputStream inputStream= Resources.getResourceAsStream("mybatis-config.xml");
  16.         //创建工厂对象
  17.         SqlSessionFactory sqlSessionFactory=new     SqlSessionFactoryBuilder().build(inputStream);
  18.         //创建session对象
  19.         SqlSession sqlSession1=sqlSessionFactory.openSession();
  20.         //获取到代理对象
  21.         UserMapper userMapper1=sqlSession1.getMapper(UserMapper.class);
  22.         //调用方法
  23.         User user1=userMapper1.findById(1);
  24.         System.out.println(user1);
  25.         System.out.println("-----------");
  26.         //手动清理缓存
  27.         sqlSession1.clearCache();
  28.         sqlSession1.commit();
  29.         sqlSession1.close();
  30.         SqlSession sqlSession2=sqlSessionFactory.openSession();
  31.         UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);
  32.         User user2=userMapper2.findById(1);
  33.         System.out.println(user2);
  34.         sqlSession2.close();
  35.         inputStream.close();
  36.     }
  37. }
复制代码
运行:


可以看出,sql语句只实验了一次,说明它是查的缓存,但是地点不一样,因为他从缓存里组装出来的






 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户云卷云舒

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表