MyBatis延迟加载和缓存(4)

一、项目创建

1、项目目录结构

2、数据库配置和上一篇的一样,这里不再描述。下面创建mybatis配置文件SqlMapConfig.xml

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE configuration
 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <configuration>
 6 <!-- 加载属性文件 -->
 7     <properties resource="db.properties"></properties>
 8
 9         <settings>
10         <!-- 打开延迟加载 的开关 -->
11         <setting name="lazyLoadingEnabled" value="true"/>
12         <!-- 将积极加载改为消极加载即按需要加载 -->
13         <setting name="aggressiveLazyLoading" value="false"/>
14         <!-- 开启二级缓存 -->
15         <setting name="cacheEnabled" value="true"/>
16     </settings>
17
18     <!-- 和spring整合后 environments配置将废除-->
19     <environments default="development">
20         <environment id="development">
21         <!-- 使用jdbc事务管理,事务控制由mybatis-->
22             <transactionManager type="JDBC" />
23         <!-- 数据库连接池,由mybatis管理-->
24             <dataSource type="POOLED">
25                 <property name="driver" value="${jdbc.driver}" />
26                 <property name="url" value="${jdbc.url}" />
27                 <property name="username" value="${jdbc.username}" />
28                 <property name="password" value="${jdbc.password}" />
29             </dataSource>
30         </environment>
31     </environments>
32
33     <mappers>
34         <mapper resource="sqlmap/User.xml"/>
35         <mapper resource="sqlmap/Orders.xml" />
36     </mappers>
37 </configuration>

3、创建映射文件User.xml和Order.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
 6 <mapper namespace="com.zhang.dao.OrdersDao">
 7     <!-- 延迟加载的resultMap -->
 8     <resultMap type="com.zhang.domain.Orders" id="OrdersUserLazyLoadingResultMap">
 9             <!--对订单信息进行映射配置  -->
10             <id column="id" property="id"/>
11             <result column="user_id" property="userId"/>
12             <result column="number" property="number"/>
13             <result column="createtime" property="createtime"/>
14             <result column="note" property="note"/>
15
16             <!-- 实现对用户信息进行延迟加载
17             select:指定延迟加载需要执行的statement的id(是根据user_id查询用户信息的statement)
18             要使用user.xml中findUserById完成根据用户id(user_id)用户信息的查询,如果findUserById不在本mapper中需要前边加namespace
19             column:订单信息中关联用户信息查询的列,是user_id
20              -->
21             <association property="user"  javaType="com.zhang.domain.User"
22              select="com.zhang.dao.UserDao.findUserById" column="user_id">
23             </association>
24     </resultMap>
25
26     <!-- 查询订单关联查询用户,用户信息需要延迟加载 -->
27     <select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingResultMap">
28         SELECT * FROM orders
29     </select>
30 </mapper>

4、各种实体类这里也不再阐述,下面之间创建接口类OrderDao.java和UserDao.java

1 package com.zhang.dao;
2
3 import java.util.List;
4
5 import com.zhang.domain.Orders;
6 public interface OrdersDao {
7         //查询订单关联查询用户,用户信息是延迟加载
8         public List<Orders> findOrdersUserLazyLoading()throws Exception;
9 }

 1 package com.zhang.dao;
 2
 3 import com.zhang.domain.User;
 4 public interface UserDao {
 5
 6     //根据id查询用户信息
 7     public User findUserById(int id) throws Exception;
 8
 9     //更新用户
10     public void updateUser(User user)throws Exception;
11
12 }

5、创建测试方法

 1 package com.zhang.test;
 2
 3 import java.io.InputStream;
 4 import java.util.List;
 5
 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.Before;
11 import org.junit.Test;
12
13 import com.zhang.dao.OrdersDao;
14 import com.zhang.dao.UserDao;
15 import com.zhang.domain.Orders;
16 import com.zhang.domain.User;
17
18 public class TestMy {
19     private SqlSessionFactory sqlSessionFactory;
20
21     // 此方法是在执行testFindUserById之前执行
22     @Before
23     public void setUp() throws Exception {
24         // 创建sqlSessionFactory
25         // mybatis配置文件
26         String resource = "SqlMapConfig.xml";
27         // 得到配置文件流
28         InputStream inputStream = Resources.getResourceAsStream(resource);
29         // 创建会话工厂,传入mybatis的配置文件信息
30         sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
31     }
32
33
34     @Test
35     public void findOrdersUserLazyLoading() throws Exception {
36         SqlSession sqlSession = sqlSessionFactory.openSession();
37         OrdersDao ordersDao = sqlSession.getMapper(OrdersDao.class);
38         List<Orders> list=ordersDao.findOrdersUserLazyLoading();
39         for (Orders orders : list) {
40         User user=    orders.getUser();
41         }
42         System.out.println(list.size());
43     }
44
45
46     // 一级缓存测试
47         @Test
48         public void testCache1() throws Exception {
49             SqlSession sqlSession = sqlSessionFactory.openSession();// 创建代理对象
50             UserDao userDao = sqlSession.getMapper(UserDao.class);
51             // 下边查询使用一个SqlSession
52             // 第一次发起请求,查询id为1的用户
53             User user1 = userDao.findUserById(1);
54             System.out.println(user1);
55             // 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
56             // 更新user1的信息
57              user1.setUsername("测试用户22");
58              userDao.updateUser(user1);
59             //执行commit操作去清空缓存
60              sqlSession.commit();
61             // 第二次发起请求,查询id为1的用户
62             User user2 = userDao.findUserById(1);
63             System.out.println(user2);
64             sqlSession.close();
65         }
66
67
68         // 二级缓存测试
69         @Test
70         public void testCache2() throws Exception {
71             SqlSession sqlSession1 = sqlSessionFactory.openSession();
72             SqlSession sqlSession2 = sqlSessionFactory.openSession();
73             SqlSession sqlSession3 = sqlSessionFactory.openSession();
74             UserDao userDao1 = sqlSession1.getMapper(UserDao.class);
75             // 第一次发起请求,查询id为1的用户
76             User user1 = userDao1.findUserById(1);
77             System.out.println(user1);
78             //这里执行关闭操作,将sqlsession中的数据写到二级缓存区域
79             sqlSession1.close();
80
81             //使用sqlSession3执行commit()操作
82             UserDao userDao3 = sqlSession3.getMapper(UserDao.class);
83             User user  = userDao3.findUserById(1);
84             user.setUsername("张明明");
85             userDao3.updateUser(user);
86             //执行提交,清空UserMapper下边的二级缓存
87             sqlSession3.commit();
88             sqlSession3.close();
89
90             UserDao userDao2 = sqlSession2.getMapper(UserDao.class);
91             // 第二次发起请求,查询id为1的用户
92             User user2 = userDao2.findUserById(1);
93             System.out.println(user2);
94             sqlSession2.close();
95         }
96
97 }

二、延迟加载

1、在order.xml文件中编写查询订单信息

在查询订单的statement中使用association去延迟加载(执行)下边的satatement(关联查询用户信息)关联查询用户信息:通过上边查询到的订单信息中user_id去关联查询用户信息。

在user.xml编写查询用户信息的映射

上边先去执行findOrdersUserLazyLoading,当需要去查询用户的时候再去执行findUserById,通过resultMap的定义将延迟加载执行配置起来。

2、延迟加载resultMap,使用association中的select指定延迟加载去执行的statement的id。

3、编写接口方法

4、测试:在程序中去遍历上一步骤查询出的List<Orders>,当我们调用Orders中的getUser方法时,开始进行延迟加载。延迟加载,去调用User.xml中findUserbyId这个方法获取用户信息。

5、延迟加载配置,mybatis默认没有开启延迟加载,需要在SqlMapConfig.xml中setting配置。

6、什么是延迟加载

resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。

需求:如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。

延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

三、查询缓存

1、什么是查询缓存

mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。mybaits提供一级缓存和二级缓存。

一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。

二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

2、一级缓存工作原理

第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。

如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

3、一级缓存测试

mybatis默认支持一级缓存,不需要在配置文件去配置。

按照上边一级缓存原理步骤去测试

控制台信息可以看出只发起了一条SQL语句

更新数据

控制台信息可以看出只发起了两条SQL语句

4、二级缓存原理

sqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。

如果SqlSession3去执行相同 mapper下sql,执行commit提交,清空该 mapper下的二级缓存区域的数据。

sqlSession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。

二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域。

UserMapper有一个二级缓存区域(按namespace分) ,其它mapper也有自己的二级缓存区域(按namespace分)。

每一个namespace的mapper都有一个二缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同 的二级缓存区域中。

5、开启二级缓存

mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。

在核心配置文件SqlMapConfig.xml中加入

在User.xml中开启二缓存,User.xml下的sql执行完成会存储到它的缓存区域(HashMap)

6、测试方法

控制台信息可以看出只发起了一条SQL语句

更新数据

控制台信息可以看出只发起了两条SQL语句

7. useCache配置

在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。

<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

总结:针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存。

8.刷新缓存

在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。

设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。

如下:

<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">

总结:一般下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。

资源下载链接:http://download.csdn.net/detail/u013865056/9907254

时间: 2024-07-29 19:49:16

MyBatis延迟加载和缓存(4)的相关文章

MyBatis延迟加载和缓存

一.延迟加载 1.主对象的加载: 根本没有延迟的概念,都是直接加载. 2.关联对象的加载时机: 01.直接加载: 访问主对象,关联对象也要加载 02.侵入式延迟: 访问主对象,并不加载关联对象 访问主对象属性的属性的时候,关联对象会被加载 03.深度延迟 访问主对象,并不加载关联对象 访问主对象的属性的时候,关联对象也不会被加载 访问关联对象或关联对象的属性的时候,才会加载关联对象. 3.一对多延迟加载代码: 01.实体类代码: package cn.pb.bean; import java.u

Mybatis延迟加载、缓存、逆向工程

一.Mybatis中的延迟加载 1.延迟加载背景:Mybatis中Mapper配置文件中的resultMap可以实现高级映射(使用association.collection实现一对一及一对多(多对多)映射),同样的association.collection具备延迟加载功能.所谓延迟加载,就是先单表查询,需要时再从关联表去关联查询(同样也可能只是是单表查询),大大单表查询速度更快,所以可以间接的提高数据库性能 2.在mybatis核心配置文件中配置,其中lazyLoadingEnabled表示

10.MyBatis 延迟加载,一级缓存,二级缓存 设置

什么是延迟加载  resultMap中的association和collection标签具有延迟加载的功能. 延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息.使用关联信息时再去加载关联信息. 设置延迟加载 需要在SqlMapConfig.xml文件中,在<settings>标签中设置下延迟加载. lazyLoadingEnabled.aggressiveLazyLoading 设置项 描述 允许值 默认值 lazyLoadingEnabled 全局性设置懒加载.如果设为'fals

Mybatis延迟加载和查询缓存

一.延迟加载 resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.collection具备延迟加载功能. 延迟加载:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快. 在mybatis核心配置文件中配置: lazyLoadingEnabled.aggressiveLazyLoading 设置项 描述 允许值 默认值 lazyLoadingEnabled 全局性设置

Mybatis(五) 延迟加载和缓存机制(一级二级缓存)

踏踏实实踏踏实实,开开心心,开心是一天不开心也是一天,路漫漫其修远兮. --WH 一.延迟加载 延迟加载就是懒加载,先去查询主表信息,如果用到从表的数据的话,再去查询从表的信息,也就是如果没用到从表的数据的话,就不查询从表的信息.所以这就是突出了懒这个特点.真是懒啊. Mybatis中resultMap可以实现延迟加载 1.1.查询订单信息,延迟加载用户信息,一对一关系. 1.1.1.开启延迟加载 全局配置文件中,settings标签用来设置全局常量的,这里就用到了. 1 <settings>

mybatis 延迟加载 ,查询缓存

阅读目录 一.延迟加载 二.查询缓存 回到顶部 一.延迟加载 resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.collection具备延迟加载功能. 延迟加载:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快. 在mybatis核心配置文件中配置: lazyLoadingEnabled.aggressiveLazyLoading 设置项 描述 允许值 默认值

MyBatis 延迟加载,一级缓存,二级缓存设置

什么是延迟加载  resultMap中的association和collection标签具有延迟加载的功能. 延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息.使用关联信息时再去加载关联信息. 设置延迟加载 需要在SqlMapConfig.xml文件中,在<settings>标签中设置下延迟加载. lazyLoadingEnabled.aggressiveLazyLoading 设置项 描述 允许值 默认值 lazyLoadingEnabled 全局性设置懒加载.如果设为'fals

mybatis 配置延迟加载 和 缓存

<!-- MyBatis延迟加载时,创建代理类 --> <dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>3.1</version> </dependency> <settings> <!-- 设置延迟加载需要添加cglib --> <!-- 全局启用或

使用Redis做MyBatis的二级缓存

1. 介绍 使用mybatis时可以使用二级缓存提高查询速度,进而改善用户体验. 使用redis做mybatis的二级缓存可是内存可控<如将单独的服务器部署出来用于二级缓存>,管理方便. 2. 使用思路 2.1 配置redis.xml 设置redis服务连接各参数 2.1 在配置文件中使用 <setting> 标签,设置开启二级缓存: 2.2 在mapper.xml 中使用<cache type="com.demo.RedisCacheClass" /&g