MyBatis延迟加载和缓存(4)
生活随笔
收集整理的這篇文章主要介紹了
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> View Code3、創建映射文件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> View Code4、各種實體類這里也不再闡述,下面之間創建接口類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 } View Code 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 } View Code5、創建測試方法
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 } View Code二、延遲加載
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轉載于:https://www.cnblogs.com/zhangjinru123/p/7221126.html
總結
以上是生活随笔為你收集整理的MyBatis延迟加载和缓存(4)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第12天,HTML基础
- 下一篇: NFS配置及使用