程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> MyBatis高等映照和查詢緩存

MyBatis高等映照和查詢緩存

編輯:關於JAVA

MyBatis高等映照和查詢緩存。本站提示廣大學習愛好者:(MyBatis高等映照和查詢緩存)文章只能為提供參考,不一定能成為您想要的結果。以下是MyBatis高等映照和查詢緩存正文


 mybatis框架履行進程:

1、設置裝備擺設mybatis的設置裝備擺設文件,SqlMapConfig.xml(稱號不固定)
2、經由過程設置裝備擺設文件,加載mybatis運轉情況,創立SqlSessionFactory會話工場
SqlSessionFactory在現實應用時按單例方法。

3、經由過程SqlSessionFactory創立SqlSession
SqlSession是一個面向用戶接口(供給操作數據庫辦法),完成對象是線程不平安的,建議sqlSession運用場所在辦法體內。

4、挪用sqlSession的辦法去操作數據。
假如須要提交事務,須要履行SqlSession的commit()辦法。

5、釋放資本,封閉SqlSession

mapper署理開辟辦法(建議應用)

只須要法式員編寫mapper接口(就是dao接口)

法式員在編寫mapper.xml(映照文件)和mapper.java須要遵守一個開辟標准:

1、mapper.xml中namespace就是mapper.java的類全途徑。

2、mapper.xml中statement的id和mapper.java中辦法名分歧。

3、mapper.xml中statement的parameterType指定輸出參數的類型和mapper.java的辦法輸出 參數類型分歧。

4、mapper.xml中statement的resultType指定輸入成果的類型和mapper.java的辦法前往值類型分歧。

本文內容:

對定單商品數據模子停止剖析。

高等映照:(懂得)

完成一對一查詢、一對多、多對多查詢。

延遲加載

查詢緩存

一級緩存

二級緩存(懂得mybatis二級緩存應用場景)

mybatis和spirng整合(控制)

逆向工程(會用)

定單商品數據模子

數據模子剖析思緒

1、每張表記載的數據內容

分模塊對每張表記載的內容停止熟習,相當於你進修體系需求(功效)的進程。

2、每張表主要的字段設置

非空字段、外鍵字段

3、數據庫級別表與表之間的關系

外鍵關系

4、表與表之間的營業關系

在剖析表與表之間的營業關系時必定要樹立在某個營業意義基本上去剖析。

數據模子剖析

用戶表user:

記載了購置商品的用戶信息

定單表:orders

記載了用戶所創立的定單(購置商品的定單)

定單明細表:orderdetail:

記載了定單的具體信息即購置商品的信息

商品表:items

記載了商品信息

表與表之間的營業關系:

在剖析表與表之間的營業關系時須要樹立在某個營業意義基本上去剖析。

先剖析數據級別之間有關系的表之間的營業關系:

usre和orders:

user—->orders : 一個用戶可以創立多個定單,一對多

orders—>user : 一個定單只由一個用戶創立,一對一

orders和orderdetail:

orders –> orderdetail:一個定單可以包含多個定單明細,由於一個定單可以購置多個商品,每一個商品的購置信息在orderdetail記載,一對多關系

orderdetail–> orders:一個定單明細只能包含在一個定單中,一對一

orderdetail和itesm:

orderdetail—> itesms:一個定單明細只對應一個商品信息,一對一

items–> orderdetail:一個商品可以包含在多個定單明細 ,一對多

再剖析數據庫級別沒有關系的表之間能否有營業關系:

orders和items:

orders和items之間可以經由過程orderdetail表樹立關系。

user 和 items : 經由過程其他表組成了多對多關系

一對一查詢

需求 : 查詢定單信息,聯系關系查詢創立定單的用戶信息

應用resultType方法查詢

sql語句應用斟酌

肯定查詢的主表:定單表

肯定查詢的聯系關系表:用戶表

聯系關系查詢應用內鏈接,照樣外鏈接?

因為orders表中有一個外鍵(user_id),經由過程外鍵聯系關系查詢用戶表只能查詢出一筆記錄,可使用內鏈接。

SELECT 
orders.*,
USER.username,
USER.sex,
USER.address 
FROM
orders,
USER 
WHERE orders.user_id = user.id

創立pojo(OrdersCustom.java)

將上邊sql查詢的成果映照到pojo中,pojo中必需包含一切查詢列名。

原始的Orders.java不克不及映照全體字段,須要新創立的pojo。

創立 一個pojo繼續包含查詢字段較多的po類。

OrdersMapperCustom.xml

OrdersMapperCustom.java

編寫測試類

選擇OrdersMapperCustom.java文件右鍵–>選擇New–>Others–> Junit Test Case–>選摘要測試的函數

在OrdersMapperCustomTest.java中編寫以下代碼:

public class OrdersMapperCustomTest {
private SqlSessionFactory sqlSessionFactory;
// 此辦法是在履行testFindUserById之前履行
@Before
public void setUp() throws Exception {
// 創立sqlSessionFactory
// mybatis設置裝備擺設文件
String resource = "SqlMapConfig.xml";
// 獲得設置裝備擺設文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 創立會話工場,傳入mybatis的設置裝備擺設文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindOrdersUser() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 創立署理對象
OrdersMapperCustom ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustom.class);
// 挪用maper的辦法
List<OrdersCustom> list = ordersMapperCustom.findOrdersUser();
System.out.println(list);
sqlSession.close();
}

應用resultMap方法查詢

sql語句 : 同resultType完成的sql

應用resultMap映照的思緒

應用resultMap將查詢成果中的定單信息映照到Orders對象中,在orders類中添加User屬性,將聯系關系查詢出來的用戶信息映照到orders對象中的user屬性中。

Orders類中添加user屬性

OrdersMapperCustom.xml

界說resultMap

tyep : 表現將全部查詢的成果映照到某個類中 eg:cn.itcast.mybatis.po.Orders

id:表現數據庫表中查詢列的獨一標識,定單信息的中的獨一標識,假如有多個列構成獨一標識,設置裝備擺設多個id

column:數據庫表中定單信息的獨一標識列

property:定單信息的獨一標識列所映照到Orders中哪一個屬性

association:用於映照聯系關系查詢單個對象的信息

property:要將聯系關系查詢的用戶信息映照到Orders中哪一個屬性

javaType:映照到user的哪一個屬性

<!-- 定單查詢聯系關系用戶的resultMap
將全部查詢的成果映照到cn.itcast.mybatis.po.Orders中
-->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserResultMap">
<!-- 設置裝備擺設映照的定單信息 -->
<!-- id:指定查詢列中的唯 一標識,定單信息的中的唯 一標識,假如有多個列構成獨一標識,設置裝備擺設多個id
column:定單信息的唯 一標識 列
property:定單信息的唯 一標識 列所映照到Orders中哪一個屬性
-->
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property=note/>
<!-- 設置裝備擺設映照的聯系關系的用戶信息 -->
<!-- association:用於映照聯系關系查詢單個對象的信息
property:要將聯系關系查詢的用戶信息映照到Orders中哪一個屬性
-->
<association property="user" javaType="cn.itcast.mybatis.po.User">
<!-- id:聯系關系查詢用戶的獨一標識
column:指定唯 一標識用戶信息的列
javaType:映照到user的哪一個屬性
-->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>

statement界說

OrdersMapperCustom.java

測試代碼

@Test
public void testFindOrdersUserResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 創立署理對象
OrdersMapperCustom ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustom.class);
// 挪用maper的辦法
List<Orders> list = ordersMapperCustom.findOrdersUserResultMap();
System.out.println(list);
sqlSession.close();
}

resultType和resultMap完成一對一查詢小結

resultType:應用resultType完成較為簡略,假如pojo中沒有包含查詢出來的列名,須要增長列名對應的屬性,便可完成映照。
假如沒有查詢成果的特別請求建議應用resultType。

resultMap:須要零丁界說resultMap,完成有點費事,假如對查詢成果有特別的請求,應用resultMap可以完成將聯系關系查詢映照pojo的屬性中。

resultMap可以完成延遲加載,resultType沒法完成延遲加載。

一對多查詢

需求 : 查詢定單及定單明細的信息。

sql語句

肯定主查詢表:定單表

肯定聯系關系查詢表:定單明細表

在一對一查詢基本上添加定單明細表聯系關系便可。

SELECT
orders.*,
USER.username,
USER.sex,
USER.address,
orderdetail.id orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id
FROM
orders,
USER,
orderdetail
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id

剖析 : 應用resultType將上邊的 查詢成果映照到pojo中,定單信息的就是反復。

請求:對orders映照不克不及湧現反復記載。

在orders.java類中添加List<orderDetail> orderDetails屬性。

終究會將定單信息映照到orders中,定單所對應的定單明細映照到orders中的orderDetails屬性中。

映照成的orders記載數為兩條(orders信息不反復)

每一個orders中的orderDetails屬性存儲了該定單所對應的定單明細。

在Orders.java中添加list定單明細屬性

OrdersMapperCustom.xml

resultMap界說

應用extends繼續,不消在中設置裝備擺設定單信息和用戶信息的映照

collection:對聯系關系查詢到多筆記錄映照到聚集對象中

property:將聯系關系查詢到多筆記錄映照到cn.itcast.mybatis.po.Orders哪一個屬性

ofType:指定映照到list聚集屬性中pojo的類型

<!-- 定單及定單明細的resultMap
應用extends繼續,不消在中設置裝備擺設定單信息和用戶信息的映照
-->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap">
<!-- 定單信息 -->
<!-- 用戶信息 -->
<!-- 應用extends繼續,不消在中設置裝備擺設定單信息和用戶信息的映照 -->
<!-- 定單明細信息
一個定單聯系關系查詢出了多條明細,要應用collection停止映照
collection:對聯系關系查詢到多筆記錄映照到聚集對象中
property:將聯系關系查詢到多筆記錄映照到cn.itcast.mybatis.po.Orders哪一個屬性
ofType:指定映照到list聚集屬性中pojo的類型
-->
<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
<!-- id:定單明細唯 一標識
property:要將定單明細的獨一標識映照到cn.itcast.mybatis.po.Orderdetail的哪一個屬性
-->
<id column="orderdetail_id" property="id"/>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="orders_id" property="ordersId"/>
</collection>
</resultMap>

OrdersMapperCustom.java

測試代碼:

@Test
public void testFindOrdersAndOrderDetailResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 創立署理對象
OrdersMapperCustom ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustom.class);
// 挪用maper的辦法
List<Orders> list = ordersMapperCustom
.findOrdersAndOrderDetailResultMap();
System.out.println(list);
sqlSession.close();
}

小結

mybatis應用resultMap的collection對聯系關系查詢的多筆記錄映照到一個list聚集屬性中。

應用resultType完成:

將定單明細映照到orders中的orderdetails中,須要本身處置,應用兩重輪回遍歷,去失落反復記載,將定單明細放在orderdetails中。

多對多查詢

需求 : 查詢用戶及用戶購置商品信息。

sql語句

查詢主表是:用戶表

聯系關系表:因為用戶和商品沒有直接聯系關系,經由過程定單和定單明細停止聯系關系,所以聯系關系表:orders、orderdetail、items

SELECT 
orders.*,
USER.username,
USER.sex,
USER.address,
orderdetail.id orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id,
items.name items_name,
items.detail items_detail,
items.price items_price
FROM
orders,
USER,
orderdetail,
items
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id AND orderdetail.items_id = items.id

映照思緒

將用戶信息映照到user中。

在user類中添加定單列表屬性List<Orders> orderslist,將用戶創立的定單映照到orderslist

在Orders中添加定單明細列表屬性List<OrderDetail>orderdetials,將定單的明細映照到orderdetials

在OrderDetail中添加Items屬性,將定單明細所對應的商品映照到Items

OrdersMapperCustom.xml

resultMap界說

<!-- 查詢用戶及購置的商品 -->
<resultMap type="cn.itcast.mybatis.po.User" id="UserAndItemsResultMap">
<!-- 用戶信息 -->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<!-- 定單信息 一個用戶對應多個定單,應用collection映照-->
<collection property="ordersList" ofType="cn.itcast.mybatis.po.Orders">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 定單明細 一個定單包含 多個明細-->
<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
<id column="orderdetail_id" property="id"/>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="orders_id" property="ordersId"/>
<!-- 商品信息一個定單明細對應一個商品-->
<association property="items" javaType="cn.itcast.mybatis.po.Items">
<id column="items_id" property="id"/>
<result column="items_name" property="name"/>
<result column="items_detail" property="detail"/>
<result column="items_price" property="price"/>
</association>
</collection>
</collection>
</resultMap>

OrdersMapperCustom.java

測試代碼:

@Test
public void testFindUserAndItemsResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 創立署理對象
OrdersMapperCustom ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustom.class);
// 挪用maper的辦法
List<User> list = ordersMapperCustom.findUserAndItemsResultMap();
System.out.println(list);
sqlSession.close();
}

多對多查詢總結

將查詢用戶購置的商品信息明細清單,(用戶名、用戶地址、購置商品稱號、購置商品時光、購置商品數目)

針對上邊的需求就應用resultType將查詢到的記載映照到一個擴大的pojo中,很簡略完成明細清單的功效。

一對多是多對多的特例,以下需求:

查詢用戶購置的商品信息,用戶和商品的關系是多對多關系。

需求1:

查詢字段:用戶賬號、用戶稱號、用戶性別、商品稱號、商品價錢(最多見)

企業開辟中罕見明細列表,用戶購置商品明細列表,

應用resultType將上邊查詢列映照到pojo輸入。

需求2:

查詢字段:用戶賬號、用戶稱號、購置商品數目、商品明細(鼠標移上顯示明細)

應用resultMap將用戶購置的商品明細列表映照到user對象中。

總結:

應用resultMap是針對那些對查詢成果映照有特別請求的功效,好比特別請求映照成list中包含多個list。

resultType與resultMap的總結

resultType:

感化:

將查詢成果依照sql列名pojo屬性名分歧性映照到pojo中。

場所:

罕見一些明細記載的展現,好比用戶購置商品明細,將聯系關系查詢信息全體展現在頁面時,此時可直接應用resultType將每筆記錄映

射到pojo中,在前端頁面遍歷list(list中是pojo)便可。

resultMap:

應用association和collection完成一對一和一對多高等映照(對成果有特別的映照請求)。

association:

感化:

將聯系關系查詢信息映照到一個pojo對象中。

場所:

為了便利查詢聯系關系信息可使用association將聯系關系定單信息映照為用戶對象的pojo屬性中,好比:查詢定單及聯系關系用戶信息。

應用resultType沒法將查詢成果映照到pojo對象的pojo屬性中,依據對成果集查詢遍歷的須要選擇應用resultType照樣resultMap。

collection:

感化:

將聯系關系查詢信息映照到一個list聚集中。

場所:
為了便利查詢遍歷聯系關系信息可使用collection將聯系關系信息映照到list聚集中,好比:查詢用戶權限規模模塊及模塊下的菜單,可以使用collection將模塊映照到模塊list中,將菜單列表映照到模塊對象的菜單list屬性中,如許的作的目標也是便利對查詢成果集停止遍歷查詢。

假如應用resultType沒法將查詢成果映照到list聚集中。

延遲加載

resultMap可以完成高等映照(應用association、collection完成一對一及一對多映照),association、collection具有延遲加載功效。

需求:

假如查詢定單而且聯系關系查詢用戶信息。假如先查詢定單信息便可知足請求,當我們須要查詢用戶信息時再查詢用戶信息。把對用戶信息的按需去查詢就是延遲加載。
延遲加載:先從單表查詢、須要時再從聯系關系表去聯系關系查詢,年夜年夜進步數據庫機能,由於查詢單表要比聯系關系查詢多張表速度要快。

應用association完成延遲加載

需求 : 查詢定單而且聯系關系查詢用戶信息

OrdresMapperCustom.xml

須要界說兩個mapper的辦法對應的statement。

1、只查詢定單信息

SELECT * FROM orders

在查詢定單的statement中應用association去延遲加載(履行)下邊的satatement(聯系關系查詢用戶信息)


2、聯系關系查詢用戶信息

經由過程上邊查詢到的定單信息中user_id去聯系關系查詢用戶信息


應用UserMapper.xml中的findUserById

上邊先去履行findOrdersUserLazyLoading,當須要去查詢用戶的時刻再去履行findUserById,經由過程resultMap的界說將延遲加載履行設置裝備擺設起來。

延遲加載resultMap

應用association中的select指定延遲加載去履行的statement的id。

<!-- 延遲加載的resultMap -->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserLazyLoadingResultMap">
<!--對定單信息停止映照設置裝備擺設 -->
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 完成對用戶信息停止延遲加載

select:指定延遲加載須要履行的statement的id(是依據user_id查詢用戶信息的statement)
要應用userMapper.xml中findUserById完成依據用戶id(user_id)用戶信息的查詢,假如findUserById不在本mapper中須要前邊加namespace

column:定單信息中聯系關系用戶信息查詢的列,是user_id

聯系關系查詢的sql懂得為:

SELECT orders.*,
(SELECT username FROM USER WHERE orders.user_id = user.id)username,
(SELECT sex FROM USER WHERE orders.user_id = user.id)sex
FROM orders
-->
<association property="user" javaType="cn.itcast.mybatis.po.User"
select="cn.itcast.mybatis.mapper.UserMapper.findUserById" column="user_id">
<!-- 完成對用戶信息停止延遲加載 -->
</association>
</resultMap>

OrderesMapperCustom.java


測試思緒:

1、履行上邊mapper辦法(findOrdersUserLazyLoading),外部去挪用cn.itcast.mybatis.mapper.OrdersMapperCustom中的findOrdersUserLazyLoading只查詢orders信息(單表)。

2、在法式中去遍歷上一步調查詢出的List<Orders>,當我們挪用Orders中的getUser辦法時,開端停止延遲加載。

3、延遲加載,去挪用UserMapper.xml中findUserbyId這個辦法獲得用戶信息。

延遲加載設置裝備擺設

mybatis默許沒有開啟延遲加載,須要在SqlMapConfig.xml中setting設置裝備擺設。

在mybatis焦點設置裝備擺設文件中設置裝備擺設:

設置項 描寫 許可值 默許值
lazyLoadingEnabled 全局性設置懶加載。假如設為‘false',則一切相干聯的都邑被初始化加載。 true or false false
aggressiveLazyLoading 當設置為‘true'的時刻,懶加載的對象能夠被任何懶屬性全體加載。不然,每一個屬性都按需加載。 true or false true

在SqlMapConfig.xml中設置裝備擺設:

測試代碼

延遲加載思慮

不應用mybatis供給的association及collection中的延遲加載功效,若何完成延遲加載?

完成辦法以下:

界說兩個mapper辦法:

1、查詢定單列表

2、依據用戶id查詢用戶信息

完成思緒:

先去查詢第一個mapper辦法,獲得定單信息列表

在法式中(service),按需去挪用第二個mapper辦法去查詢用戶信息。

總之:應用延遲加載辦法,先去查詢簡略的sql(最好單表,也能夠聯系關系查詢),再去按須要加載聯系關系查詢的其它信息。

查詢緩存

mybatis供給查詢緩存,用於加重數據壓力,進步數據庫機能。

mybaits供給一級緩存,和二級緩存。

一級緩存是SqlSession級其余緩存。在操作數據庫時須要結構 sqlSession對象,在對象中有一個數據構造(HashMap)用於存儲緩存數據。分歧的sqlSession之間的緩存數據區域(HashMap)是相互不影響的。

二級緩存是mapper級其余緩存,多個SqlSession去操作統一個Mapper的sql語句,多個SqlSession可以共用二級緩存,二級緩存是跨SqlSession的。

為何要用緩存?

假如緩存中稀有據就不消從數據庫中獲得,年夜年夜進步體系機能。

一級緩存

一級緩存任務道理

第一次提議查詢用戶id為1的用戶信息,先去找緩存中能否有id為1的用戶信息,假如沒有,從數據庫查詢用戶信息。

獲得用戶信息,將用戶信息存儲到一級緩存中。

假如sqlSession去履行commit操作(履行拔出、更新、刪除),清空SqlSession中的一級緩存,如許做的目標為了讓緩存中存儲的是最新的信息,防止髒讀。

第二次提議查詢用戶id為1的用戶信息,先去找緩存中能否有id為1的用戶信息,緩存中有,直接從緩存中獲得用戶信息。

一級緩存測試

mybatis默許支撐一級緩存,不須要在設置裝備擺設文件去設置裝備擺設。

依照上邊一級緩存道理步調去測試。

//OrdersMapperCusntomTest.java
@Test
public void testCache1() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();//創立署理對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//下邊查詢應用一個SqlSession
//第一次提議要求,查詢id為1的用戶
User user1 = userMapper.findUserById(1);
System.out.println(user1);
// 假如sqlSession去履行commit操作(履行拔出、更新、刪除),清空SqlSession中的一級緩存,如許做的目標為了讓緩存中存儲的是最新的信息,防止髒讀。
//更新user1的信息
user1.setUsername("測試用戶22");
userMapper.updateUser(user1);
//履行commit操作去清空緩存
sqlSession.commit();
//第二次提議要求,查詢id為1的用戶
User user2 = userMapper.findUserById(1);
System.out.println(user2);
sqlSession.close();
}

一級緩存運用

正式開辟,是將mybatis和spring停止整合開辟,事務掌握在service中。

一個service辦法中包含 許多mapper辦法挪用。

service{
//開端履行時,開啟事務,創立SqlSession對象
//第一次挪用mapper的辦法findUserById(1)
//第二次挪用mapper的辦法findUserById(1),從一級緩存中取數據
//辦法停止,sqlSession封閉
}

假如是履行兩次service挪用查詢雷同 的用戶信息,不走一級緩存,由於session辦法停止,sqlSession就封閉,一級緩存就清空。

二級緩存

道理

起首開啟mybatis的二級緩存。

sqlSession1去查詢用戶id為1的用戶信息,查詢到用戶信息會將查詢數據存儲到二級緩存中。

假如SqlSession3去履行雷同 mapper下sql,履行commit提交,清空該 mapper下的二級緩存區域的數據。

sqlSession2去查詢用戶id為1的用戶信息,去緩存中找能否存在數據,假如存在直接從緩存中掏出數據。

二級緩存與一級緩存差別,二級緩存的規模更年夜,多個sqlSession可以同享一個UserMapper的二級緩存區域。

UserMapper有一個二級緩存區域(按namespace分) ,其它mapper也有本身的二級緩存區域(按namespace分)。

每個namespace的mapper都有一個二緩存區域,兩個mapper的namespace假如雷同,這兩個mapper履行sql查詢到數據將存在雷同的二級緩存區域中。

開啟二級緩存

mybaits的二級緩存是mapper規模級別,除在SqlMapConfig.xml設置二級緩存的總開關,還要在詳細的mapper.xml中開啟二級緩存。

在焦點設置裝備擺設文件SqlMapConfig.xml中參加

<setting name="cacheEnabled" value="true"/>

描寫 許可值 默許值

cacheEnabled 對在此設置裝備擺設文件下的一切cache 停止全局性開/關設置。 true or false

在UserMapper.xml中開啟二級緩存,UserMapper.xml下的sql履行完成會存儲到它的緩存區域(HashMap)。

挪用pojo類完成序列化接口

為了將緩存數據掏出履行反序列化操作,由於二級緩存數據存儲介質多種多樣,紛歧樣在內存。

二級緩存測試

@Test
public void testCache2() throws Exception {
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
SqlSession sqlSession3 = sqlSessionFactory.openSession();
// 創立署理對象
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
// 第一次提議要求,查詢id為1的用戶
User user1 = userMapper1.findUserById(1);
System.out.println(user1);
//這裡履行封閉操作,將sqlsession中的數據寫到二級緩存區域
sqlSession1.close();
//應用sqlSession3履行commit()操作
UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);
User user = userMapper3.findUserById(1);
user.setUsername("張明明");
userMapper3.updateUser(user);
//履行提交,清空UserMapper下邊的二級緩存
sqlSession3.commit();
sqlSession3.close();
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
// 第二次提議要求,查詢id為1的用戶
User user2 = userMapper2.findUserById(1);
System.out.println(user2);
sqlSession2.close();
}

useCache設置裝備擺設

在statement中設置useCache=false可以禁用以後select語句的二級緩存,即每次查詢都邑收回sql去查詢,默許情形是true,即該sql應用二級緩存。

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

總結:針對每次查詢都須要最新的數據sql,要設置成useCache=false,禁用二級緩存。

刷新緩存

就是清空緩存

在mapper的統一個namespace中,假如有其它insert、update、delete操作數據後須要刷新緩存,假如不履行刷新緩存會湧現髒讀。

設置statement設置裝備擺設中的flushCache=”true” 屬性,默許情形下為true即刷新緩存,假如改成false則不會刷新。應用緩存時假如手動修正數據庫表中的查詢數據會湧現髒讀。

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

總結:普通下履行完commit操作都須要刷新緩存,flushCache=true表現刷新緩存,如許可以免數據庫髒讀。

mybatis整合ehcache

ehcache是一個散布式緩存框架。

散布緩存

我們體系為了進步體系並發,機能、普通對體系停止散布式安排(集群安排方法)
不應用散布緩存,緩存的數據在各各辦事零丁存儲,不便利體系 開辟。所以要應用散布式緩存對緩存數據停止集中治理。
mybatis沒法完成散布式緩存,須要和其它散布式緩存框架停止整合。

整合ehcache辦法(控制)

mybatis供給了一個cache接口,假如要完成本身的緩存邏輯,完成cache接口開辟便可。
mybatis和ehcache整合,mybatis和ehcache整合包中供給了一個cache接口的完成類。

mybatis默許完成cache類是:


參加ehcache包

整合ehcache

設置裝備擺設mapper中cache中的type為ehcache對cache接口的完成類型。

參加ehcache的設置裝備擺設文件(在classpath下設置裝備擺設ehcache.xml)

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="F:\develop\ehcache" />
<defaultCache 
maxElementsInMemory="1000" 
maxElementsOnDisk="10000000"
eternal="false" 
overflowToDisk="false" 
timeToIdleSeconds="120"
timeToLiveSeconds="120" 
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>

屬性解釋:

diskStore:指定命據在磁盤中的存儲地位。
defaultCache:當借助CacheManager.add(“demoCache”)創立Cache時,EhCache便會采取<defalutCache/>指定的的治理戰略

以部屬性是必需的:

maxElementsInMemory - 在內存中緩存的element的最年夜數量
maxElementsOnDisk - 在磁盤上緩存的element的最年夜數量,若是0表現無限年夜
eternal - 設定緩存的elements能否永久不外期。假如為true,則緩存的數據一直有用,假如為false那末還要依據timeToIdleSeconds,timeToLiveSeconds斷定
overflowToDisk - 設定當內存緩存溢出的時刻能否將過時的element緩存到磁盤上

以部屬性是可選的:

timeToIdleSeconds - 當緩存在EhCache中的數據前後兩次拜訪的時光跨越timeToIdleSeconds的屬性取值時,這些數據便會刪除,默許值是0,也就是可閒置時光無限年夜
timeToLiveSeconds - 緩存element的有用性命期,默許是0.,也就是element存活時光無限年夜
diskSpoolBufferSizeMB 這個參數設置DiskStore(磁盤緩存)的緩存區年夜小.默許是30MB.每一個Cache都應當有本身的一個緩沖區.
diskPersistent - 在VM重啟的時刻能否啟用磁盤保留EhCache中的數據,默許是false。
diskExpiryThreadIntervalSeconds - 磁盤緩存的清算線程運轉距離,默許是120秒。每一個120s,響應的線程會停止一次EhCache中數據的清算任務
memoryStoreEvictionPolicy - 當內存緩存到達最年夜,有新的element參加的時刻, 移除緩存中element的戰略。默許是LRU(比來起碼應用),可選的有LFU(最不常應用)和FIFO(先輩先出)

二級運用場景

關於拜訪多的查詢要求且用戶對查詢成果及時性請求不高,此時可采取mybatis二級緩存技巧下降數據庫拜訪量,進步拜訪速度,營業場景好比:耗時較高的統計剖析sql、德律風賬單查詢sql等。

完成辦法以下:經由過程設置刷新距離時光,由mybatis每隔一段時光主動清空緩存,依據數據變更頻率設置緩存刷新距離flushInterval,好比設置為30分鐘、60分鐘、24小時等,依據需求而定。

二級緩存局限性

mybatis二級緩存對細粒度的數據級其余緩存完成欠好,好比以下需求:對商品信息停止緩存,因為商品信息查詢拜訪量年夜,然則請求用戶每次都能查詢最新的商品信息,此時假如應用mybatis的二級緩存就沒法完成當一個商品變更時只刷新該商品的緩存信息而不刷新其它商品的信息,由於mybaits的二級緩存區域以mapper為單元劃分,當一個商品信息變更會將一切商品信息的緩存數據全體清空。處理此類成績須要在營業層依據需求對數據有針對性緩存。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved