摘要:訂單信息與訂單明細為一對多關系。例如先從單表查詢,需要時再從關聯表去關聯查詢,大大提高數據庫性能,因為查詢單表要比關聯查詢多張表速度要快。作用將關聯查詢信息映射到一個對象中。
MyBatis理解與掌握(關聯查詢)
@(MyBatis)[Java, 框架, MyBatis]
一對一查詢案例:查詢所有訂單信息,關聯查詢下單用戶信息
從Order的角度,一個訂單對應一個用戶:order----->user (一對一)
從User的角度,一個用戶可以有多個訂單:user------>order (多對一)
場景需求:查詢訂單,同時關聯查詢用戶信息
-------------------------------表設計------------------------------------------
在t_orders(多方表)中增加一個字段user_id,作為外鍵
-------------------------------類設計------------------------------------------
public class Order { private int oId; private int number; private User user; //省略get、set方法 } public class User { private Integer userId; private String userName; //省略get、set方法 }
-----------------------映射文件mapping.xml-----------------------
方法一:嵌套結果
association標簽可用的屬性如下:
property:對象屬性的名稱 javaType:對象屬性的類型 column:所對應的外鍵字段名稱 select:使用另一個查詢封裝的結果 columnPrefix:當連接多表時,你將不得不使用列別名來避免ResultSet中的重復列名。指定columnPrefix允許你映射列名到一個外部的結果集中。
執行過程:
DEBUG [main] - ==> Preparing: select t_orders.order_id, t_orders.order_number, t_user.id, t_user.user_name, t_user.user_address from t_orders,t_user WHERE t_orders.user_id = t_user.id and t_orders.order_id = ? DEBUG [main] - ==> Parameters: 1(Integer) TRACE [main] - <== Columns: order_id, order_number, id, user_name, user_address TRACE [main] - <== Row: 1, 30, 1, zhangsan, 北京 DEBUG [main] - <== Total: 1 打印查詢結果對象: Order [oId=1, number=30, user=User [userId=1, userName=zhangsan]]方法二:嵌套查詢
通過執行另外一個SQL映射語句來返回預期的復雜類型
---------------------------java代碼---------------------
@Test public void test() { SqlSession session = DBUtil.getSession(); Order order = session.selectOne("getOrder",1 ); System.out.println("打印查詢結果對象:"+order); }
--------------------------sql執行過程-------------------------
DEBUG [main] - ==> Preparing: select order_id, order_number, user_id from t_orders WHERE order_id = ? DEBUG [main] - ==> Parameters: 1(Integer) TRACE [main] - <== Columns: order_id, order_number, user_id TRACE [main] - <== Row: 1, 30, 3 DEBUG [main] - ====> Preparing: select user_id as userId , user_name as userName from t_user WHERE user_id=? DEBUG [main] - ====> Parameters: 3(Integer) TRACE [main] - <==== Columns: userId, userName TRACE [main] - <==== Row: 3, wangwu DEBUG [main] - <==== Total: 1 DEBUG [main] - <== Total: 1 打印查詢結果對象:Order [oId=1, number=30, user=User [userId=3, userName=wangwu]]
__注意__:我們有兩個查詢語句:一個來加載order,另外一個來加載user。
這種方式很簡單, 但會產生 “N+1 查詢問題”。概括地講,N+1 查詢問題可以是這樣引起的:
(1)你執行了一個多帶帶的 SQL 語句來獲取結果列表(就是“+1”)。 (2)假設返回的是一個集合,集合中的每個元素對應了一條記錄,你還需要執行了一個查詢語句來為每條記錄加載細節(就是“N”)。
MyBatis 延遲加載是一種處理方式,然而,如果你加載一個列表,之后迅速迭代來訪問嵌套的數據,你會調用所有的延遲加載,問題沒有解決。
方法三:增加一個包含訂單信息和用戶信息的類,用這個類作為返回類型 resultTypepublic class OrdersCustom extends Orders { private String username ; // 用戶名稱 private String address ; // 用戶地址 省略get、set方法 }
總結:定義專門的po類作為輸出類型,其中定義了sql查詢結果集所有的字段。此方法較為簡單,企業中普遍使用。
案例:通過訂單id查詢訂單信息及訂單下的訂單明細信息。
訂單信息與訂單明細為一對多關系。
---------------------------類設計----------------------------------------
private int oId; private int number; //訂單編號 private User user; //用戶信息 private Listorderdetails; //訂單詳情信息 //省略get、set方法 }
-------------------------映射文件-----------------------------
方法一:嵌套結果使用繼承extends,上面的
打印查詢結果對象:Order [oId=1, number=30000001, user=User [userId=3, userName=wangwu], orderdetails=[Orderdetail [odId=1, itemsId=2, itemsNum=30], Orderdetail [odId=2, itemsId=1, itemsNum=32]]]方法二:嵌套查詢
---------------------------java代碼---------------------
@Test public void test() { SqlSession session = DBUtil.getSession(); Order order = session.selectOne("getOrder",1 ); System.out.println("打印查詢結果對象:"+order); }
------------------------sql執行結果-----------------------
打印查詢結果對象:Order [oId=1, number=30000001, user=User [userId=3, userName=wangwu], orderdetails=[Orderdetail [odId=1, itemsId=2, itemsNum=30], Orderdetail [odId=2, itemsId=1, itemsNum=32]]]
案例:查詢用戶購買的商品信息
需要查詢所有用戶信息,關聯查詢訂單及訂單明細信息,訂單明細信息中關聯查詢商品信息
分析:
需要關聯查詢映射的信息是:訂單、訂單明細、商品信息
訂單:一個用戶對應多個訂單,使用 collection 映射到用戶對象的訂單列表屬性中
訂單明細:一個訂單對應多個明細,使用 collection 映射到訂單對象中的明細屬性中
商品信息: 一個訂單明細對應一個商品, 使用 association 映射到訂單明細對象的商品屬性中。
---------------------------類設計-----------------------------------
public class User { private Integer userId; private String userName; private Listorders; //訂單列表 } public class Order { private int oId; private int number; //訂單編號 private List orderdetails; //訂單詳情信息 } public class Orderdetail { private int odId; private Items item; //商品信息 private int itemsNum; //商品數量 } public class Items { private int itemId; private String itemName; //商品名稱 }
-----------------------------映射文件--------------------------------------
---------------------------java代碼---------------------
@Test public void test() { SqlSession session = DBUtil.getSession(); Listusers = session.selectList("getUser"); for (User user : users) { System.out.println("打印用戶信息:"+user); } }
------------------------sql執行結果-----------------------
打印用戶信息:User [userId=1, userName=zhangsan, orders=[Order [oId=1, number=30000001, orderdetails=[Orderdetail [odId=1, item=Items [itemId=2, itemName=香蕉], itemsNum=30], Orderdetail [odId=2, item=Items [itemId=1, itemName=蘋果], itemsNum=32]]], Order [oId=3, number=30000003, orderdetails=[Orderdetail [odId=3, item=Items [itemId=3, itemName=橘子], itemsNum=25]]]]] 打印用戶信息:User [userId=3, userName=wangwu, orders=[Order [oId=4, number=30000004, orderdetails=[Orderdetail [odId=4, item=Items [itemId=3, itemName=橘子], itemsNum=45]]]]]自關聯 延遲加載
什么是延遲加載
resultMap可實現高級映射(使用association、collection實現一對一及一對多映射),association、collection具備延遲加載功能。
例如:先從單表查詢,需要時再從關聯表去關聯查詢,大大 提高數據庫性能 ,因為查詢單表要比關聯查詢多張表速度要快。
mybatis框架默認不支持延遲加載功能,如果想要使用,需要啟用延遲加載功能
默認框架會采用侵入式的延遲加載:
如果查詢主動方數據,而不使用,那么關聯數據是不會被查詢的。
如果使用了主動方的數據,那么關聯數據即使沒有使用也會被查詢。
可以禁用侵入式延遲加載功能
綜上所述,在主配置文件mybatis-config.xml中做如下配置:
注意一個異常:Caused by: org.xml.sax.SAXParseException; lineNumber: 36; columnNumber: 17; 元素類型為 "configuration" 的內容必須匹配 "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)"。
在關聯的元素(association ,collection ,discriminator)中,我們存在一個屬性: fetchType來決定是否需要延遲加載,如果配置它,它將覆蓋掉原有在MyBatis設置的策略。
對于它而言,它有兩個取值:
* lazy: 延遲加載(默認) * eager:即刻加載
由它來決定是否需要延遲或者即刻加載。
總結 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 集合中。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/77174.html
摘要:容器自動完成裝載,默認的方式是這部分重點在常用模塊的使用以及的底層實現原理。 對于那些想面試高級 Java 崗位的同學來說,除了算法屬于比較「天方夜譚」的題目外,剩下針對實際工作的題目就屬于真正的本事了,熱門技術的細節和難點成為了主要考察的內容。 這里說「天方夜譚」并不是說算法沒用,不切實際,而是想說算法平時其實很少用到,甚至面試官都對自己出的算法題一知半解。 這里總結打磨了 70 道...
摘要:語句在代碼中硬編碼,造成代碼不易于維護,實際應用變化的可能較大,變動需要改變代碼。對結果集解析存在硬編碼查詢列名,變化導致解析代碼變化,系統不易于維護,如果能將數據庫記錄封裝成對象解析比較方便。 MyBatis理解與掌握(簡介) @(MyBatis)[Java, 框架, MyBatis] 簡介 ??Mybatis是一個數據持久層框架,MyBatis消除了幾乎所有的JDBC代碼和參數的手...
摘要:理解與掌握緩存框架一級緩存默認就可以使用框架處理緩存是依賴映射,的內部緩存使用一個,為語句。一級緩存的作用域是一個,一旦發生變化,一級緩存失敗在同一個中,執行相同的查詢,第一次會去查詢數據庫,并寫到緩存中第二次直接從緩存中取。 MyBatis理解與掌握(緩存) @(MyBatis)[Java, 框架, MyBatis] 一級緩存(SqlSession) 默認就可以使用 框架處理緩存是 ...
摘要:輸入參數類型指定輸入參數類型,通過從輸入對象中獲取參數值放置在中。查詢結果處理指定輸出結果類型,將查詢結果的一行記錄數據映射為指定類型的對象。 MyBatis理解與掌握(輸入與輸出) @(MyBatis)[Java, 框架, MyBatis] 占位符和拼接 {}:占位符 能防止sql注入問題,所一能盡量用#{}就盡量用#{}用來傳入參數,sql在解析的時候會加上 當成字符串來解析 ,...
摘要:本文速覽本篇文章是我為接下來的源碼分析系列文章寫的一個導讀文章。年該項目從基金會遷出,并改名為。同期,停止維護。符號所在的行則是表示的執行結果。同時,使用無需處理受檢異常,比如。另外,把寫在配置文件中,進行集中管理,利于維護。 1.本文速覽 本篇文章是我為接下來的 MyBatis 源碼分析系列文章寫的一個導讀文章。本篇文章從 MyBatis 是什么(what),為什么要使用(why),...
閱讀 1364·2021-11-22 15:25
閱讀 3358·2021-10-21 09:38
閱讀 1575·2021-10-19 13:21
閱讀 1000·2021-09-06 15:00
閱讀 1679·2019-08-30 15:44
閱讀 2595·2019-08-29 15:40
閱讀 3447·2019-08-29 13:44
閱讀 2055·2019-08-26 16:56