多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > 數據庫 > 數據庫應用 > MyBatis入門第2天--高級映射與查詢緩存

MyBatis入門第2天--高級映射與查詢緩存

來源:程序員人生   發布時間:2016-07-23 10:33:26 閱讀次數:4562次
文檔版本 開發工具 測試平臺 工程名字 日期 作者 備注
V1.0 2016.06.28 lutianfei none

  • mybatis框架履行進程:

    • 1、配置mybatis的配置文件,SqlMapConfig.xml(名稱不固定)
    • 2、通過配置文件,加載mybatis運行環境,創建SqlSessionFactory會話工廠
      • SqlSessionFactory在實際使用時按單例方式。
    • 3、通過SqlSessionFactory創建SqlSession
      • SqlSession是1個面向用戶接口(提供操作數據庫方法),實現對象是線程不安全的,建議sqlSession利用場合在方法體內。
    • 4、調用sqlSession的方法去操作數據。
      • 如果需要提交事務,需要履行SqlSession的commit()方法。
    • 5、釋放資源,關閉SqlSession
  • mapper代理開發方法(建議使用)

    • 只需要程序員編寫mapper接口(就是dao接口)
    • 程序員在編寫mapper.xml(映照文件)和mapper.java需要遵守1個開發規范:
    • 1、mapper.xml中namespace就是mapper.java的類全路徑。
    • 2、mapper.xml中statement的id和mapper.java中方法名1致。
    • 3、mapper.xml中statement的parameterType指定輸入參數的類型和mapper.java的方法輸入 參數類型1致。
    • 4、mapper.xml中statement的resultType指定輸出結果的類型和mapper.java的方法返回值類型1致。
  • 本文內容:

    • 對定單商品數據模型進行分析。
    • 高級映照:(了解)
      • 實現1對1查詢、1對多、多對多查詢。
      • 延遲加載
    • 查詢緩存
      • 1級緩存
      • 2級緩存(了解mybatis2級緩存使用處景)
    • mybatis和spirng整合(掌握)
    • 逆向工程(會用)

定單商品數據模型

數據模型分析思路

  • 1、每張表記錄的數據內容
    • 分模塊對每張表記錄的內容進行熟習,相當于你學習系統需求(功能)的進程。
  • 2、每張表重要的字段設置
    • 非空字段、外鍵字段
  • 3、數據庫級別表與表之間的關系
    • 外鍵關系
  • 4、表與表之間的業務關系
    • 在分析表與表之間的業務關系時1定要建立在某個業務意義基礎上去分析
數據模型分析

  • 用戶表user:
    • 記錄了購買商品的用戶信息
  • 定單表:orders
    • 記錄了用戶所創建的定單(購買商品的定單)
  • 定單明細表:orderdetail:
    • 記錄了定單的詳細信息即購買商品的信息
  • 商品表:items

    • 記錄了商品信息
  • 表與表之間的業務關系:
    在分析表與表之間的業務關系時需要建立在某個業務意義基礎上去分析。

  • 先分析數據級別之間有關系的表之間的業務關系:

  • usre和orders:

    • user—->orders : 1個用戶可以創建多個定單,1對多
    • orders—>user : 1個定單只由1個用戶創建,1對1
  • orders和orderdetail:

    • orders –> orderdetail:1個定單可以包括多個定單明細,由于1個定單可以購買多個商品,每一個商品的購買信息在orderdetail記錄,1對多關系
    • orderdetail–> orders:1個定單明細只能包括在1個定單中,1對1
  • orderdetail和itesm:

    • orderdetail—> itesms:1個定單明細只對應1個商品信息,1對1
    • items–> orderdetail:1個商品可以包括在多個定單明細 ,1對多
  • 再分析數據庫級別沒有關系的表之間是不是有業務關系:

    • orders和items:
      • orders和items之間可以通過orderdetail表建立關系。
    • user 和 items : 通過其他表構成了多對多關系


1對1查詢

  • 需求 : 查詢定單信息,關聯查詢創建定單的用戶信息
使用resultType方式查詢
  • sql語句使用斟酌
  • 肯定查詢的主表:定單表
  • 肯定查詢的關聯表:用戶表
  • 關聯查詢使用內鏈接,還是外鏈接?
    • 由于orders表中有1個外鍵(user_id),通過外鍵關聯查詢用戶表只能查詢出1條記錄,可使用內鏈接。
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。
    • 創建 1個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:表示數據庫表中查詢列的唯1標識,定單信息的中的唯1標識,如果有多個列組成唯1標識,配置多個id
      • column:數據庫表中定單信息的唯1標識列
      • property:定單信息的唯1標識列所映照到Orders中哪一個屬性
      • association:用于映照關聯查詢單個對象的信息
      • property:要將關聯查詢的用戶信息映照到Orders中哪一個屬性
      • javaType:映照到user的哪一個屬性
<!-- 定單查詢關聯用戶的resultMap 將全部查詢的結果映照到cn.itcast.mybatis.po.Orders中 --> <resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserResultMap"> <!-- 配置映照的定單信息 --> <!-- id:指定查詢列中的唯 1標識,定單信息的中的唯 1標識,如果有多個列組成唯1標識,配置多個id column:定單信息的唯 1標識 列 property:定單信息的唯 1標識 列所映照到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:關聯查詢用戶的唯1標識 column:指定唯 1標識用戶信息的列 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實現1對1查詢小結
  • resultType:使用resultType實現較為簡單,如果pojo中沒有包括查詢出來的列名,需要增加列名對應的屬性,便可完成映照。
  • 如果沒有查詢結果的特殊要求建議使用resultType。

  • resultMap:需要單獨定義resultMap,實現有點麻煩,如果對查詢結果有特殊的要求,使用resultMap可以完成將關聯查詢映照pojo的屬性中。

  • resultMap可以實現延遲加載,resultType沒法實現延遲加載。


1對多查詢

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

  • sql語句

    • 肯定主查詢表:定單表
    • 肯定關聯查詢表:定單明細表
    • 在1對1查詢基礎上添加定單明細表關聯便可。
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繼承,不用在中配置定單信息和用戶信息的映照 --> <!-- 定單明細信息 1個定單關聯查詢出了多條明細,要使用collection進行映照 collection:對關聯查詢到多條記錄映照到集合對象中 property:將關聯查詢到多條記錄映照到cn.itcast.mybatis.po.Orders哪一個屬性 ofType:指定映照到list集合屬性中pojo的類型 --> <collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail"> <!-- id:定單明細唯 1標識 property:要將定單明細的唯1標識映照到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對關聯查詢的多條記錄映照到1個list集合屬性中。
    • 使用resultType實現:
      • 將定單明細映照到orders中的orderdetails中,需要自己處理,使用兩重循環遍歷,去掉重復記錄,將定單明細放在orderdetails中。


多對多查詢

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

  • sql語句

    • 查詢主表是:用戶表
    • 關聯表:由于用戶和商品沒有直接關聯,通過定單定單明細進行關聯,所以關聯表:ordersorderdetailitems
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"/> <!-- 定單信息 1個用戶對應多個定單,使用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"/> <!-- 定單明細 1個定單包括 多個明細--> <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"/> <!-- 商品信息1個定單明細對應1個商品--> <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將查詢到的記錄映照到1個擴大的pojo中,很簡單實現明細清單的功能。
  • 1對多是多對多的特例,以下需求:

    • 查詢用戶購買的商品信息,用戶和商品的關系是多對多關系。
    • 需求1:
      • 查詢字段:用戶賬號、用戶名稱、用戶性別、商品名稱、商品價格(最多見)
      • 企業開發中常見明細列表,用戶購買商品明細列表,
      • 使用resultType將上邊查詢列映照到pojo輸出。
    • 需求2:
      • 查詢字段:用戶賬號、用戶名稱、購買商品數量、商品明細(鼠標移上顯示明細)
      • 使用resultMap將用戶購買的商品明細列表映照到user對象中。
  • 總結:

    • 使用resultMap是針對那些對查詢結果映照有特殊要求的功能,比如特殊要求映照成list中包括多個list。

resultType與resultMap的總結

  • resultType:
  • 作用:
    • 將查詢結果依照sql列名pojo屬性名1致性映照到pojo中。
  • 場合:

    • 常見1些明細記錄的展現,比如用戶購買商品明細,將關聯查詢信息全部展現在頁面時,此時可直接使用resultType將每條記錄映照到pojo中,在前端頁面遍歷list(list中是pojo)便可。
  • resultMap:

    • 使用association和collection完成1對1和1對多高級映照(對結果有特殊的映照要求)。
  • association:

  • 作用:
    • 將關聯查詢信息映照到1個pojo對象中。
  • 場合:

    • 為了方便查詢關聯信息可使用association將關聯定單信息映照為用戶對象的pojo屬性中,比如:查詢定單及關聯用戶信息。
    • 使用resultType沒法將查詢結果映照到pojo對象的pojo屬性中,根據對結果集查詢遍歷的需要選擇使用resultType還是resultMap。
  • collection:

  • 作用:
    • 將關聯查詢信息映照到1個list集合中。
  • 場合:
    • 為了方便查詢遍歷關聯信息可使用collection將關聯信息映照到list集合中,比如:查詢用戶權限范圍模塊及模塊下的菜單,可以使用collection將模塊映照到模塊list中,將菜單列表映照到模塊對象的菜單list屬性中,這樣的作的目的也是方便對查詢結果集進行遍歷查詢。
    • 如果使用resultType沒法將查詢結果映照到list集合中。


延遲加載

  • resultMap可以實現高級映照(使用association、collection實現1對1及1對多映照),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、在程序中去遍歷上1步驟查詢出的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查詢用戶信息
    • 實現思路:
      • 先去查詢第1個mapper方法,獲得定單信息列表
      • 在程序中(service),按需去調用第2個mapper方法去查詢用戶信息。
  • 總之:使用延遲加載方法,先去查詢簡單的sql(最好單表,也能夠關聯查詢),再去按需要加載關聯查詢的其它信息。




查詢緩存

  • mybatis提供查詢緩存,用于減輕數據壓力,提高數據庫性能。
  • mybaits提供1級緩存,和2級緩存。

  • 1級緩存是SqlSession級別的緩存。在操作數據庫時需要構造 sqlSession對象,在對象中有1個數據結構(HashMap)用于存儲緩存數據。不同的sqlSession之間的緩存數據區域(HashMap)是相互不影響的。

  • 2級緩存是mapper級別的緩存,多個SqlSession去操作同1個Mapper的sql語句,多個SqlSession可以共用2級緩存,2級緩存是跨SqlSession的。

  • 為何要用緩存?

    • 如果緩存中有數據就不用從數據庫中獲得,大大提高系統性能。


1級緩存

  • 1級緩存工作原理

  • 第1次發起查詢用戶id為1的用戶信息,先去找緩存中是不是有id為1的用戶信息,如果沒有,從數據庫查詢用戶信息。

  • 得到用戶信息,將用戶信息存儲到1級緩存中。
  • 如果sqlSession去履行commit操作(履行插入、更新、刪除),清空SqlSession中的1級緩存,這樣做的目的為了讓緩存中存儲的是最新的信息,避免臟讀。
  • 第2次發起查詢用戶id為1的用戶信息,先去找緩存中是不是有id為1的用戶信息,緩存中有,直接從緩存中獲得用戶信息。

1級緩存測試

  • mybatis默許支持1級緩存,不需要在配置文件去配置。
  • 依照上邊1級緩存原理步驟去測試。
//OrdersMapperCusntomTest.java @Test public void testCache1() throws Exception{ SqlSession sqlSession = sqlSessionFactory.openSession();//創建代理對象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //下邊查詢使用1個SqlSession //第1次發起要求,查詢id為1的用戶 User user1 = userMapper.findUserById(1); System.out.println(user1); // 如果sqlSession去履行commit操作(履行插入、更新、刪除),清空SqlSession中的1級緩存,這樣做的目的為了讓緩存中存儲的是最新的信息,避免臟讀。 //更新user1的信息 user1.setUsername("測試用戶22"); userMapper.updateUser(user1); //履行commit操作去清空緩存 sqlSession.commit(); //第2次發起要求,查詢id為1的用戶 User user2 = userMapper.findUserById(1); System.out.println(user2); sqlSession.close(); }


  • 1級緩存利用
    • 正式開發,是將mybatis和spring進行整合開發,事務控制在service中。
    • 1個service方法中包括 很多mapper方法調用。
service{ //開始履行時,開啟事務,創建SqlSession對象 //第1次調用mapper的方法findUserById(1) //第2次調用mapper的方法findUserById(1),從1級緩存中取數據 //方法結束,sqlSession關閉 }
  • 如果是履行兩次service調用查詢相同 的用戶信息,不走1級緩存,由于session方法結束,sqlSession就關閉,1級緩存就清空。


2級緩存

  • 原理

  • 首先開啟mybatis的2級緩存。

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

  • 如果SqlSession3去履行相同 mapper下sql,履行commit提交,清空該 mapper下的2級緩存區域的數據。

  • sqlSession2去查詢用戶id為1的用戶信息,去緩存中找是不是存在數據,如果存在直接從緩存中取出數據。

  • 2級緩存與1級緩存區分,2級緩存的范圍更大,多個sqlSession可以同享1個UserMapper的2級緩存區域。

  • UserMapper有1個2級緩存區域(按namespace分) ,其它mapper也有自己的2級緩存區域(按namespace分)。
  • 每個namespace的mapper都有1個2緩存區域,兩個mapper的namespace如果相同,這兩個mapper履行sql查詢到數據將存在相同的2級緩存區域中。
開啟2級緩存
  • mybaits的2級緩存是mapper范圍級別,除在SqlMapConfig.xml設置2級緩存的總開關,還要在具體的mapper.xml中開啟2級緩存。
  • 在核心配置文件SqlMapConfig.xml中加入
    • <setting name="cacheEnabled" value="true"/>
描寫 允許值 默許值
cacheEnabled 對在此配置文件下的所有cache 進行全局性開/關設置。 true or false
  • 在UserMapper.xml中開啟2級緩存,UserMapper.xml下的sql履行完成會存儲到它的緩存區域(HashMap)。


  • 調用pojo類實現序列化接口

    • 為了將緩存數據取出履行反序列化操作,由于2級緩存數據存儲介質多種多樣,不1樣在內存。
  • 2級緩存測試

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


useCache配置
  • 在statement中設置useCache=false可以禁用當前select語句的2級緩存,即每次查詢都會發出sql去查詢,默許情況是true,即該sql使用2級緩存。
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
  • 總結:針對每次查詢都需要最新的數據sql,要設置成useCache=false,禁用2級緩存。
刷新緩存
  • 就是清空緩存
  • 在mapper的同1個namespace中,如果有其它insert、update、delete操作數據后需要刷新緩存,如果不履行刷新緩存會出現臟讀。
  • 設置statement配置中的flushCache=”true” 屬性,默許情況下為true即刷新緩存,如果改成false則不會刷新。使用緩存時如果手動修改數據庫表中的查詢數據會出現臟讀。
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">
  • 總結:1般下履行完commit操作都需要刷新緩存,flushCache=true表示刷新緩存,這樣可以免數據庫臟讀。


mybatis整合ehcache
  • ehcache是1個散布式緩存框架。

  • 散布緩存

    • 我們系統為了提高系統并發,性能、1般對系統進行散布式部署(集群部署方式)
    • 不使用散布緩存,緩存的數據在各各服務單獨存儲,不方便系統 開發。所以要使用散布式緩存對緩存數據進行集中管理。
    • mybatis沒法實現散布式緩存,需要和其它散布式緩存框架進行整合。


整合ehcache方法(掌握)
  • mybatis提供了1個cache接口,如果要實現自己的緩存邏輯,實現cache接口開發便可。
  • mybatis和ehcache整合,mybatis和ehcache整合包中提供了1個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都應當有自己的1個緩沖區.
  • diskPersistent - 在VM重啟的時候是不是啟用磁盤保存EhCache中的數據,默許是false。
  • diskExpiryThreadIntervalSeconds - 磁盤緩存的清算線程運行間隔,默許是120秒。每一個120s,相應的線程會進行1次EhCache中數據的清算工作
  • memoryStoreEvictionPolicy - 當內存緩存到達最大,有新的element加入的時候, 移除緩存中element的策略。默許是LRU(最近最少使用),可選的有LFU(最不常使用)和FIFO(先進先出)
2級利用場景
  • 對訪問多的查詢要求且用戶對查詢結果實時性要求不高,此時可采取mybatis2級緩存技術下降數據庫訪問量,提高訪問速度,業務場景比如:耗時較高的統計分析sql、電話賬單查詢sql等。
  • 實現方法以下:通過設置刷新間隔時間,由mybatis每隔1段時間自動清空緩存,根據數據變化頻率設置緩存刷新間隔flushInterval,比如設置為30分鐘、60分鐘、24小時等,根據需求而定。
2級緩存局限性
  • mybatis2級緩存對細粒度的數據級別的緩存實現不好,比如以下需求:對商品信息進行緩存,由于商品信息查詢訪問量大,但是要求用戶每次都能查詢最新的商品信息,此時如果使用mybatis的2級緩存就沒法實現當1個商品變化時只刷新該商品的緩存信息而不刷新其它商品的信息,由于mybaits的2級緩存區域以mapper為單位劃分,當1個商品信息變化會將所有商品信息的緩存數據全部清空。解決此類問題需要在業務層根據需求對數據有針對性緩存。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国产一级在线观看视频 | 日本69av| 精品一区二区三区四区在线 | 一级做a爰性色毛片免费 | 日本爱爱免费视频 | 视频三区 | 亚洲综合久久成人69 | 日韩欧美天堂 | 最近好看中文字幕视频 | 日本一区二区三区四区无限 | 欧美啊啊| 国产午夜亚洲精品久久www | 不卡视频一区二区三区 | 手机看片国产欧美日韩高清 | 欧美18一19sex极品 | 国产乱码亚洲精品一区二区 | 成人午夜视频在线播放 | 亚洲国产福利精品一区二区 | 亚洲爽爽网 | 波多野结衣在线观看一区二区三区 | 深爱激情五月婷婷 | 亚洲国产视频网站 | 免费观看成人www精品视频在线 | 国产精品特黄毛片 | 日韩亚洲色图 | 精品国产精品 | 成人欧美一区二区三区在线观看 | 久久久久一区二区三区 | 婷婷色九月综合激情丁香 | 成人精品一区二区激情 | 性欧美高清极品猛交 | free性欧美极度另类3d | 欧美激情久久久久久久大片 | 夜夜精品视频一区二区 | 国产日韩欧美一区二区三区视频 | 在线观看免费精品国自产 | 福利视频一区二区三区 | 国产一区二区三区四区在线观看 | 午夜视频高清在线aaa | 欧美a在线看 | 久久久青草青青国产亚洲免观 |