日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > 數(shù)據(jù)庫 > 數(shù)據(jù)庫應(yīng)用 > MyBatis入門第2天--高級(jí)映射與查詢緩存

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

來源:程序員人生   發(fā)布時(shí)間:2016-07-23 10:33:26 閱讀次數(shù):4578次
文檔版本 開發(fā)工具 測(cè)試平臺(tái) 工程名字 日期 作者 備注
V1.0 2016.06.28 lutianfei none

  • mybatis框架履行進(jìn)程:

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

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

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

定單商品數(shù)據(jù)模型

數(shù)據(jù)模型分析思路

  • 1、每張表記錄的數(shù)據(jù)內(nèi)容
    • 分模塊對(duì)每張表記錄的內(nèi)容進(jìn)行熟習(xí),相當(dāng)于你學(xué)習(xí)系統(tǒng)需求(功能)的進(jìn)程。
  • 2、每張表重要的字段設(shè)置
    • 非空字段、外鍵字段
  • 3、數(shù)據(jù)庫級(jí)別表與表之間的關(guān)系
    • 外鍵關(guān)系
  • 4、表與表之間的業(yè)務(wù)關(guān)系
    • 在分析表與表之間的業(yè)務(wù)關(guān)系時(shí)1定要建立在某個(gè)業(yè)務(wù)意義基礎(chǔ)上去分析
數(shù)據(jù)模型分析

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

    • 記錄了商品信息
  • 表與表之間的業(yè)務(wù)關(guān)系:
    在分析表與表之間的業(yè)務(wù)關(guān)系時(shí)需要建立在某個(gè)業(yè)務(wù)意義基礎(chǔ)上去分析。

  • 先分析數(shù)據(jù)級(jí)別之間有關(guān)系的表之間的業(yè)務(wù)關(guān)系:

  • usre和orders:

    • user—->orders : 1個(gè)用戶可以創(chuàng)建多個(gè)定單,1對(duì)多
    • orders—>user : 1個(gè)定單只由1個(gè)用戶創(chuàng)建,1對(duì)1
  • orders和orderdetail:

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

    • orderdetail—> itesms:1個(gè)定單明細(xì)只對(duì)應(yīng)1個(gè)商品信息,1對(duì)1
    • items–> orderdetail:1個(gè)商品可以包括在多個(gè)定單明細(xì) ,1對(duì)多
  • 再分析數(shù)據(jù)庫級(jí)別沒有關(guān)系的表之間是不是有業(yè)務(wù)關(guān)系:

    • orders和items:
      • orders和items之間可以通過orderdetail表建立關(guān)系。
    • user 和 items : 通過其他表構(gòu)成了多對(duì)多關(guān)系


1對(duì)1查詢

  • 需求 : 查詢定單信息,關(guān)聯(lián)查詢創(chuàng)建定單的用戶信息
使用resultType方式查詢
  • sql語句使用斟酌
  • 肯定查詢的主表:定單表
  • 肯定查詢的關(guān)聯(lián)表:用戶表
  • 關(guān)聯(lián)查詢使用內(nèi)鏈接,還是外鏈接?
    • 由于orders表中有1個(gè)外鍵(user_id),通過外鍵關(guān)聯(lián)查詢用戶表只能查詢出1條記錄,可使用內(nèi)鏈接。
SELECT orders.*, USER.username, USER.sex, USER.address FROM orders, USER WHERE orders.user_id = user.id


  • 創(chuàng)建pojo(OrdersCustom.java)
    • 將上邊sql查詢的結(jié)果映照到pojo中,pojo中必須包括所有查詢列名。
    • 原始的Orders.java不能映照全部字段,需要新創(chuàng)建的pojo。
    • 創(chuàng)建 1個(gè)pojo繼承包括查詢字段較多的po類。


  • OrdersMapperCustom.xml


  • OrdersMapperCustom.java

  • 編寫測(cè)試類

    • 選擇OrdersMapperCustom.java文件右鍵–>選擇New–>Others–> Junit Test Case–>選擇要測(cè)試的函數(shù)
    • 在OrdersMapperCustomTest.java中編寫以下代碼:
public class OrdersMapperCustomTest { private SqlSessionFactory sqlSessionFactory; // 此方法是在履行testFindUserById之前履行 @Before public void setUp() throws Exception { // 創(chuàng)建sqlSessionFactory // mybatis配置文件 String resource = "SqlMapConfig.xml"; // 得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); // 創(chuàng)建會(huì)話工廠,傳入mybatis的配置文件信息 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindOrdersUser() throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); // 創(chuàng)建代理對(duì)象 OrdersMapperCustom ordersMapperCustom = sqlSession .getMapper(OrdersMapperCustom.class); // 調(diào)用maper的方法 List<OrdersCustom> list = ordersMapperCustom.findOrdersUser(); System.out.println(list); sqlSession.close(); }


使用resultMap方式查詢
  • sql語句 : 同resultType實(shí)現(xiàn)的sql

  • 使用resultMap映照的思路

    • 使用resultMap將查詢結(jié)果中的定單信息映照到Orders對(duì)象中,在orders類中添加User屬性,將關(guān)聯(lián)查詢出來的用戶信息映照到orders對(duì)象中的user屬性中。
  • Orders類中添加user屬性

  • OrdersMapperCustom.xml

    • 定義resultMap
      • tyep : 表示將全部查詢的結(jié)果映照到某個(gè)類中 eg:cn.itcast.mybatis.po.Orders
      • id:表示數(shù)據(jù)庫表中查詢列的唯1標(biāo)識(shí),定單信息的中的唯1標(biāo)識(shí),如果有多個(gè)列組成唯1標(biāo)識(shí),配置多個(gè)id
      • column:數(shù)據(jù)庫表中定單信息的唯1標(biāo)識(shí)列
      • property:定單信息的唯1標(biāo)識(shí)列所映照到Orders中哪一個(gè)屬性
      • association:用于映照關(guān)聯(lián)查詢單個(gè)對(duì)象的信息
      • property:要將關(guān)聯(lián)查詢的用戶信息映照到Orders中哪一個(gè)屬性
      • javaType:映照到user的哪一個(gè)屬性
<!-- 定單查詢關(guān)聯(lián)用戶的resultMap 將全部查詢的結(jié)果映照到cn.itcast.mybatis.po.Orders中 --> <resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserResultMap"> <!-- 配置映照的定單信息 --> <!-- id:指定查詢列中的唯 1標(biāo)識(shí),定單信息的中的唯 1標(biāo)識(shí),如果有多個(gè)列組成唯1標(biāo)識(shí),配置多個(gè)id column:定單信息的唯 1標(biāo)識(shí) 列 property:定單信息的唯 1標(biāo)識(shí) 列所映照到Orders中哪一個(gè)屬性 --> <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/> <!-- 配置映照的關(guān)聯(lián)的用戶信息 --> <!-- association:用于映照關(guān)聯(lián)查詢單個(gè)對(duì)象的信息 property:要將關(guān)聯(lián)查詢的用戶信息映照到Orders中哪一個(gè)屬性 --> <association property="user" javaType="cn.itcast.mybatis.po.User"> <!-- id:關(guān)聯(lián)查詢用戶的唯1標(biāo)識(shí) column:指定唯 1標(biāo)識(shí)用戶信息的列 javaType:映照到user的哪一個(gè)屬性 --> <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

  • 測(cè)試代碼

@Test public void testFindOrdersUserResultMap() throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); // 創(chuàng)建代理對(duì)象 OrdersMapperCustom ordersMapperCustom = sqlSession .getMapper(OrdersMapperCustom.class); // 調(diào)用maper的方法 List<Orders> list = ordersMapperCustom.findOrdersUserResultMap(); System.out.println(list); sqlSession.close(); }


resultType和resultMap實(shí)現(xiàn)1對(duì)1查詢小結(jié)
  • resultType:使用resultType實(shí)現(xiàn)較為簡(jiǎn)單,如果pojo中沒有包括查詢出來的列名,需要增加列名對(duì)應(yīng)的屬性,便可完成映照。
  • 如果沒有查詢結(jié)果的特殊要求建議使用resultType。

  • resultMap:需要單獨(dú)定義resultMap,實(shí)現(xiàn)有點(diǎn)麻煩,如果對(duì)查詢結(jié)果有特殊的要求,使用resultMap可以完成將關(guān)聯(lián)查詢映照pojo的屬性中。

  • resultMap可以實(shí)現(xiàn)延遲加載,resultType沒法實(shí)現(xiàn)延遲加載。


1對(duì)多查詢

  • 需求 : 查詢定單及定單明細(xì)的信息。

  • sql語句

    • 肯定主查詢表:定單表
    • 肯定關(guān)聯(lián)查詢表:定單明細(xì)表
    • 在1對(duì)1查詢基礎(chǔ)上添加定單明細(xì)表關(guān)聯(lián)便可。
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將上邊的 查詢結(jié)果映照到pojo中,定單信息的就是重復(fù)。

  • 要求:對(duì)orders映照不能出現(xiàn)重復(fù)記錄。

    • 在orders.java類中添加List<orderDetail> orderDetails屬性。
    • 終究會(huì)將定單信息映照到orders中,定單所對(duì)應(yīng)的定單明細(xì)映照到orders中的orderDetails屬性中。
    • 映照成的orders記錄數(shù)為兩條(orders信息不重復(fù))
    • 每一個(gè)orders中的orderDetails屬性存儲(chǔ)了該定單所對(duì)應(yīng)的定單明細(xì)。

  • 在Orders.java中添加list定單明細(xì)屬性

  • OrdersMapperCustom.xml


  • resultMap定義
    • 使用extends繼承,不用在中配置定單信息和用戶信息的映照
    • collection:對(duì)關(guān)聯(lián)查詢到多條記錄映照到集合對(duì)象中
    • property:將關(guān)聯(lián)查詢到多條記錄映照到cn.itcast.mybatis.po.Orders哪一個(gè)屬性
    • ofType:指定映照到list集合屬性中pojo的類型
<!-- 定單及定單明細(xì)的resultMap 使用extends繼承,不用在中配置定單信息和用戶信息的映照 --> <resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap"> <!-- 定單信息 --> <!-- 用戶信息 --> <!-- 使用extends繼承,不用在中配置定單信息和用戶信息的映照 --> <!-- 定單明細(xì)信息 1個(gè)定單關(guān)聯(lián)查詢出了多條明細(xì),要使用collection進(jìn)行映照 collection:對(duì)關(guān)聯(lián)查詢到多條記錄映照到集合對(duì)象中 property:將關(guān)聯(lián)查詢到多條記錄映照到cn.itcast.mybatis.po.Orders哪一個(gè)屬性 ofType:指定映照到list集合屬性中pojo的類型 --> <collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail"> <!-- id:定單明細(xì)唯 1標(biāo)識(shí) property:要將定單明細(xì)的唯1標(biāo)識(shí)映照到cn.itcast.mybatis.po.Orderdetail的哪一個(gè)屬性 --> <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

  • 測(cè)試代碼:

@Test public void testFindOrdersAndOrderDetailResultMap() throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); // 創(chuàng)建代理對(duì)象 OrdersMapperCustom ordersMapperCustom = sqlSession .getMapper(OrdersMapperCustom.class); // 調(diào)用maper的方法 List<Orders> list = ordersMapperCustom .findOrdersAndOrderDetailResultMap(); System.out.println(list); sqlSession.close(); }


  • 小結(jié)
    • mybatis使用resultMap的collection對(duì)關(guān)聯(lián)查詢的多條記錄映照到1個(gè)list集合屬性中。
    • 使用resultType實(shí)現(xiàn):
      • 將定單明細(xì)映照到orders中的orderdetails中,需要自己處理,使用兩重循環(huán)遍歷,去掉重復(fù)記錄,將定單明細(xì)放在orderdetails中。


多對(duì)多查詢

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

  • sql語句

    • 查詢主表是:用戶表
    • 關(guān)聯(lián)表:由于用戶和商品沒有直接關(guān)聯(lián),通過定單定單明細(xì)進(jìn)行關(guān)聯(lián),所以關(guān)聯(lián)表: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,將用戶創(chuàng)建的定單映照到orderslist
    • 在Orders中添加定單明細(xì)列表屬性List<OrderDetail>orderdetials,將定單的明細(xì)映照到orderdetials
    • 在OrderDetail中添加Items屬性,將定單明細(xì)所對(duì)應(yīng)的商品映照到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個(gè)用戶對(duì)應(yīng)多個(gè)定單,使用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"/> <!-- 定單明細(xì) 1個(gè)定單包括 多個(gè)明細(xì)--> <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個(gè)定單明細(xì)對(duì)應(yīng)1個(gè)商品--> <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

  • 測(cè)試代碼:

@Test public void testFindUserAndItemsResultMap() throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); // 創(chuàng)建代理對(duì)象 OrdersMapperCustom ordersMapperCustom = sqlSession .getMapper(OrdersMapperCustom.class); // 調(diào)用maper的方法 List<User> list = ordersMapperCustom.findUserAndItemsResultMap(); System.out.println(list); sqlSession.close(); }


  • 多對(duì)多查詢總結(jié)
    • 將查詢用戶購買的商品信息明細(xì)清單,(用戶名、用戶地址、購買商品名稱、購買商品時(shí)間、購買商品數(shù)量)
    • 針對(duì)上邊的需求就使用resultType將查詢到的記錄映照到1個(gè)擴(kuò)大的pojo中,很簡(jiǎn)單實(shí)現(xiàn)明細(xì)清單的功能。
  • 1對(duì)多是多對(duì)多的特例,以下需求:

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

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

resultType與resultMap的總結(jié)

  • resultType:
  • 作用:
    • 將查詢結(jié)果依照sql列名pojo屬性名1致性映照到pojo中。
  • 場(chǎng)合:

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

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

  • 作用:
    • 將關(guān)聯(lián)查詢信息映照到1個(gè)pojo對(duì)象中。
  • 場(chǎng)合:

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

  • 作用:
    • 將關(guān)聯(lián)查詢信息映照到1個(gè)list集合中。
  • 場(chǎng)合:
    • 為了方便查詢遍歷關(guān)聯(lián)信息可使用collection將關(guān)聯(lián)信息映照到list集合中,比如:查詢用戶權(quán)限范圍模塊及模塊下的菜單,可以使用collection將模塊映照到模塊list中,將菜單列表映照到模塊對(duì)象的菜單list屬性中,這樣的作的目的也是方便對(duì)查詢結(jié)果集進(jìn)行遍歷查詢。
    • 如果使用resultType沒法將查詢結(jié)果映照到list集合中。


延遲加載

  • resultMap可以實(shí)現(xiàn)高級(jí)映照(使用association、collection實(shí)現(xiàn)1對(duì)1及1對(duì)多映照),association、collection具有延遲加載功能。

  • 需求:

    • 如果查詢定單并且關(guān)聯(lián)查詢用戶信息。如果先查詢定單信息便可滿足要求,當(dāng)我們需要查詢用戶信息時(shí)再查詢用戶信息。把對(duì)用戶信息的按需去查詢就是延遲加載。
  • 延遲加載:先從單表查詢、需要時(shí)再從關(guān)聯(lián)表去關(guān)聯(lián)查詢,大大提高數(shù)據(jù)庫性能,由于查詢單表要比關(guān)聯(lián)查詢多張表速度要快。

使用association實(shí)現(xiàn)延遲加載
  • 需求 : 查詢定單并且關(guān)聯(lián)查詢用戶信息

  • OrdresMapperCustom.xml

  • 需要定義兩個(gè)mapper的方法對(duì)應(yīng)的statement。

    • 1、只查詢定單信息

      • SELECT * FROM orders
      • 在查詢定單的statement中使用association去延遲加載(履行)下邊的satatement(關(guān)聯(lián)查詢用戶信息)

      • 2、關(guān)聯(lián)查詢用戶信息

      • 通過上邊查詢到的定單信息中user_id去關(guān)聯(lián)查詢用戶信息
      • 使用UserMapper.xml中的findUserById
  • 上邊先去履行findOrdersUserLazyLoading,當(dāng)需要去查詢用戶的時(shí)候再去履行findUserById,通過resultMap的定義將延遲加載履行配置起來。

  • 延遲加載resultMap

    • 使用association中的select指定延遲加載去履行的statement的id。
<!-- 延遲加載的resultMap --> <resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserLazyLoadingResultMap"> <!--對(duì)定單信息進(jìn)行映照配置 --> <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"/> <!-- 實(shí)現(xiàn)對(duì)用戶信息進(jìn)行延遲加載 select:指定延遲加載需要履行的statement的id(是根據(jù)user_id查詢用戶信息的statement) 要使用userMapper.xml中findUserById完成根據(jù)用戶id(user_id)用戶信息的查詢,如果findUserById不在本mapper中需要前邊加namespace column:定單信息中關(guān)聯(lián)用戶信息查詢的列,是user_id 關(guān)聯(lián)查詢的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"> <!-- 實(shí)現(xiàn)對(duì)用戶信息進(jìn)行延遲加載 --> </association> </resultMap>


  • OrderesMapperCustom.java

  • 測(cè)試思路:

    • 1、履行上邊mapper方法(findOrdersUserLazyLoading),內(nèi)部去調(diào)用cn.itcast.mybatis.mapper.OrdersMapperCustom中的findOrdersUserLazyLoading只查詢orders信息(單表)。
    • 2、在程序中去遍歷上1步驟查詢出的List<Orders>,當(dāng)我們調(diào)用Orders中的getUser方法時(shí),開始進(jìn)行延遲加載。
    • 3、延遲加載,去調(diào)用UserMapper.xml中findUserbyId這個(gè)方法獲得用戶信息。
延遲加載配置
  • mybatis默許沒有開啟延遲加載,需要在SqlMapConfig.xml中setting配置。

  • 在mybatis核心配置文件中配置:

設(shè)置項(xiàng) 描寫 允許值 默許值
lazyLoadingEnabled 全局性設(shè)置懶加載。如果設(shè)為‘false’,則所有相干聯(lián)的都會(huì)被初始化加載。 true or false false
aggressiveLazyLoading 當(dāng)設(shè)置為‘true’的時(shí)候,懶加載的對(duì)象可能被任何懶屬性全部加載。否則,每一個(gè)屬性都按需加載。 true or false true
  • 在SqlMapConfig.xml中配置:

  • 測(cè)試代碼

  • 延遲加載思考

    • 不使用mybatis提供的association及collection中的延遲加載功能,如何實(shí)現(xiàn)延遲加載?
  • 實(shí)現(xiàn)方法以下:

    • 定義兩個(gè)mapper方法:
      • 1、查詢定單列表
      • 2、根據(jù)用戶id查詢用戶信息
    • 實(shí)現(xiàn)思路:
      • 先去查詢第1個(gè)mapper方法,獲得定單信息列表
      • 在程序中(service),按需去調(diào)用第2個(gè)mapper方法去查詢用戶信息。
  • 總之:使用延遲加載方法,先去查詢簡(jiǎn)單的sql(最好單表,也能夠關(guān)聯(lián)查詢),再去按需要加載關(guān)聯(lián)查詢的其它信息。




查詢緩存

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

  • 1級(jí)緩存是SqlSession級(jí)別的緩存。在操作數(shù)據(jù)庫時(shí)需要構(gòu)造 sqlSession對(duì)象,在對(duì)象中有1個(gè)數(shù)據(jù)結(jié)構(gòu)(HashMap)用于存儲(chǔ)緩存數(shù)據(jù)。不同的sqlSession之間的緩存數(shù)據(jù)區(qū)域(HashMap)是相互不影響的。

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

  • 為何要用緩存?

    • 如果緩存中有數(shù)據(jù)就不用從數(shù)據(jù)庫中獲得,大大提高系統(tǒng)性能。


1級(jí)緩存

  • 1級(jí)緩存工作原理

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

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

1級(jí)緩存測(cè)試

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


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


2級(jí)緩存

  • 原理

  • 首先開啟mybatis的2級(jí)緩存。

  • sqlSession1去查詢用戶id為1的用戶信息,查詢到用戶信息會(huì)將查詢數(shù)據(jù)存儲(chǔ)到2級(jí)緩存中。

  • 如果SqlSession3去履行相同 mapper下sql,履行commit提交,清空該 mapper下的2級(jí)緩存區(qū)域的數(shù)據(jù)。

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

  • 2級(jí)緩存與1級(jí)緩存區(qū)分,2級(jí)緩存的范圍更大,多個(gè)sqlSession可以同享1個(gè)UserMapper的2級(jí)緩存區(qū)域。

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


  • 調(diào)用pojo類實(shí)現(xiàn)序列化接口

    • 為了將緩存數(shù)據(jù)取出履行反序列化操作,由于2級(jí)緩存數(shù)據(jù)存儲(chǔ)介質(zhì)多種多樣,不1樣在內(nèi)存。
  • 2級(jí)緩存測(cè)試

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


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


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

  • 散布緩存

    • 我們系統(tǒng)為了提高系統(tǒng)并發(fā),性能、1般對(duì)系統(tǒng)進(jìn)行散布式部署(集群部署方式)
    • 不使用散布緩存,緩存的數(shù)據(jù)在各各服務(wù)單獨(dú)存儲(chǔ),不方便系統(tǒng) 開發(fā)。所以要使用散布式緩存對(duì)緩存數(shù)據(jù)進(jìn)行集中管理。
    • mybatis沒法實(shí)現(xiàn)散布式緩存,需要和其它散布式緩存框架進(jìn)行整合。


整合ehcache方法(掌握)
  • mybatis提供了1個(gè)cache接口,如果要實(shí)現(xiàn)自己的緩存邏輯,實(shí)現(xiàn)cache接口開發(fā)便可。
  • mybatis和ehcache整合,mybatis和ehcache整合包中提供了1個(gè)cache接口的實(shí)現(xiàn)類。

  • mybatis默許實(shí)現(xiàn)cache類是:

  • 加入ehcache包

  • 整合ehcache

    • 配置mapper中cache中的type為ehcache對(duì)cache接口的實(shí)現(xiàn)類型。
  • 加入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:指定數(shù)據(jù)在磁盤中的存儲(chǔ)位置。
    • defaultCache:當(dāng)借助CacheManager.add(“demoCache”)創(chuàng)建Cache時(shí),EhCache便會(huì)采取<defalutCache/>指定的的管理策略
  • 以下屬性是必須的:
    • maxElementsInMemory - 在內(nèi)存中緩存的element的最大數(shù)目
    • maxElementsOnDisk - 在磁盤上緩存的element的最大數(shù)目,若是0表示無窮大
    • eternal - 設(shè)定緩存的elements是不是永久不過期。如果為true,則緩存的數(shù)據(jù)始終有效,如果為false那末還要根據(jù)timeToIdleSeconds,timeToLiveSeconds判斷
    • overflowToDisk - 設(shè)定當(dāng)內(nèi)存緩存溢出的時(shí)候是不是將過期的element緩存到磁盤上
  • 以下屬性是可選的:
    • timeToIdleSeconds - 當(dāng)緩存在EhCache中的數(shù)據(jù)前后兩次訪問的時(shí)間超過timeToIdleSeconds的屬性取值時(shí),這些數(shù)據(jù)便會(huì)刪除,默許值是0,也就是可閑置時(shí)間無窮大
    • timeToLiveSeconds - 緩存element的有效生命期,默許是0.,也就是element存活時(shí)間無窮大
      • diskSpoolBufferSizeMB 這個(gè)參數(shù)設(shè)置DiskStore(磁盤緩存)的緩存區(qū)大小.默許是30MB.每一個(gè)Cache都應(yīng)當(dāng)有自己的1個(gè)緩沖區(qū).
  • diskPersistent - 在VM重啟的時(shí)候是不是啟用磁盤保存EhCache中的數(shù)據(jù),默許是false。
  • diskExpiryThreadIntervalSeconds - 磁盤緩存的清算線程運(yùn)行間隔,默許是120秒。每一個(gè)120s,相應(yīng)的線程會(huì)進(jìn)行1次EhCache中數(shù)據(jù)的清算工作
  • memoryStoreEvictionPolicy - 當(dāng)內(nèi)存緩存到達(dá)最大,有新的element加入的時(shí)候, 移除緩存中element的策略。默許是LRU(最近最少使用),可選的有LFU(最不常使用)和FIFO(先進(jìn)先出)
2級(jí)利用場(chǎng)景
  • 對(duì)訪問多的查詢要求且用戶對(duì)查詢結(jié)果實(shí)時(shí)性要求不高,此時(shí)可采取mybatis2級(jí)緩存技術(shù)下降數(shù)據(jù)庫訪問量,提高訪問速度,業(yè)務(wù)場(chǎng)景比如:耗時(shí)較高的統(tǒng)計(jì)分析sql、電話賬單查詢sql等。
  • 實(shí)現(xiàn)方法以下:通過設(shè)置刷新間隔時(shí)間,由mybatis每隔1段時(shí)間自動(dòng)清空緩存,根據(jù)數(shù)據(jù)變化頻率設(shè)置緩存刷新間隔flushInterval,比如設(shè)置為30分鐘、60分鐘、24小時(shí)等,根據(jù)需求而定。
2級(jí)緩存局限性
  • mybatis2級(jí)緩存對(duì)細(xì)粒度的數(shù)據(jù)級(jí)別的緩存實(shí)現(xiàn)不好,比如以下需求:對(duì)商品信息進(jìn)行緩存,由于商品信息查詢?cè)L問量大,但是要求用戶每次都能查詢最新的商品信息,此時(shí)如果使用mybatis的2級(jí)緩存就沒法實(shí)現(xiàn)當(dāng)1個(gè)商品變化時(shí)只刷新該商品的緩存信息而不刷新其它商品的信息,由于mybaits的2級(jí)緩存區(qū)域以mapper為單位劃分,當(dāng)1個(gè)商品信息變化會(huì)將所有商品信息的緩存數(shù)據(jù)全部清空。解決此類問題需要在業(yè)務(wù)層根據(jù)需求對(duì)數(shù)據(jù)有針對(duì)性緩存。
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 成人av免费在线看 | 福利片一区二区 | 亚洲视频在线免费 | 福利在线观看 | 日本一区二区三区视频在线播放 | 成人夜晚看av | 精品国产乱码久久久久久久 | 91免费在线播放 | 久草av在线播放 | 亚洲永久免费 | 伊人国产在线观看 | 不卡一二区 | 日韩一级免费 | 久久99精品久久久久久久 | 久久久久综合网 | 欧美一级欧美一级在线播放 | 美女网站视频色 | 成年人在线看 | 一区二区三区国产精品 | 国产亚洲网站 | 国产999精品久久久 亚洲视频二区 | 日韩一区二区在线看 | 久久精品一| 亚洲一区二区三区久久 | 综合久久av| 在线日韩中文字幕 | 久久成人免费视频 | 成人教育av | 日韩一区二区三区四区五区 | 激情综合五月 | 国产美女在线播放 | 成人传媒 | 性疯狂做受xxxx高清视频 | 一区二区三区中文字幕 | 国产自产21区 | 亚洲成人综合在线 | 国产精品18 | 99午夜 | 国产精品自在线拍国产 | 人人澡人人添人人爽一区二区 | 国产成人精品白浆久久69 |