小結:
mybatis是什么?
mybatis是一人持久層框架,mybatis是一個不完全的ORM框架。sql語句需要程序員自己去編寫,但是mybatis也有映射(輸入參數映射、輸出結果映射)。
mybatis入門門檻不高,學習成本低,讓程序員把精力放在sql語句上,對sql語句優化非常方便,適用與需求變化較多項目,比如互聯網項目。
mybatis框架執行過程:
1、配置mybatis的配置文件,SqlMapConfig.xml(名稱不固定)
2、通過配置文件,加載mybatis運行環境,創建SqlSessionFactory會話工廠
SqlSessionFactory在實際使用時按單例方式。
3、通過SqlSessionFactory創建SqlSession
SqlSession是一個面向用戶接口(提供操作數據庫方法),實現對象是線程不安全的,建議sqlSession應用場合在方法體內。
4、調用sqlSession的方法去操作數據。
如果需要提交事務,需要執行SqlSession的commit()方法。
5、釋放資源,關閉SqlSession
mybatis開發dao的方法:
1、原始dao 的方法
需要程序員編寫dao接口和實現類
需要在dao實現類中注入一個SqlSessionFactory工廠。
2、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的方法返回值類型一致。
SqlMapConfig.xml配置文件:可以配置properties屬性、別名、mapper加載。。。
輸入映射:
parameterType:指定輸入參數類型可以簡單類型、pojo、hashmap。。
對於綜合查詢,建議parameterType使用包裝的pojo,有利於系統 擴展。
輸出映射:
resultType:
查詢到的列名和resultType指定的pojo的屬性名一致,才能映射成功。
reusltMap:
可以通過resultMap 完成一些高級映射。
如果查詢到的列名和映射的pojo的屬性名不一致時,通過resultMap設置列名和屬性名之間的對應關系(映射關系)。可以完成映射。
高級映射:
將關聯查詢的列映射到一個pojo屬性中。(一對一)
將關聯查詢的列映射到一個List<pojo>中。(一對多)
1 訂單商品數據模型
用戶表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表建立 關系。
1.一對一查詢
1.1:resultType
1.1.1 需求
查詢訂單信息,關聯查詢創建訂單的用戶信息
1.1.2sql語句
確定查詢的主表:訂單表
確定查詢的關聯表:用戶表
關聯查詢使用內鏈接?還是外鏈接?
由於orders表中有一個外鍵(user_id),通過外鍵關聯查詢用戶表只能查詢出一條記錄,可以使用內鏈接。
SELECT orders.*, USER.username,USER.sex,USER.address FROM orders,USER WHERE orders.user_id = user.id
1.1.3 創建pojo
將上邊sql查詢的結果映射到pojo中,pojo中必須包括所有查詢列名。
原始的Orders.java不能映射全部字段,需要新創建的pojo。
創建 一個pojo繼承包括查詢字段較多的po類。
1.1.4 mapper.xml
1.1.5 mapper.java
1.2 resultMap
1.2.1 sql語句
同resultType實現的sql
1.2.2 使用resultMap映射的思路
使用resultMap將查詢結果中的訂單信息映射到Orders對象中,在orders類中添加User屬性,將關聯查詢出來的用戶信息映射到orders對象中的user屬性中。
1.2.3 需要Orders類中添加user屬性
1.2.4 mapper.xml
<!-- 訂單查詢關聯用戶的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>
1.2.5mapper.java
1.3 resultType和resultMap實現一對一查詢小結
實現一對一查詢:
resultType:使用resultType實現較為簡單,如果pojo中沒有包括查詢出來的列名,需要增加列名對應的屬性,即可完成映射。
如果沒有查詢結果的特殊要求建議使用resultType。
resultMap:需要單獨定義resultMap,實現有點麻煩,如果對查詢結果有特殊的要求,使用resultMap可以完成將關聯查詢映射pojo的屬性中。
resultMap可以實現延遲加載,resultType無法實現延遲加載。
2. 一對多查詢
2.1 需求:
查詢訂單及訂單明細的信息。
2.2sql語句
確定主查詢表:訂單表
確定關聯查詢表:訂單明細表
在一對一查詢基礎上添加訂單明細表關聯即可。
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
2.3 分析
使用resultType將上邊的 查詢結果映射到pojo中,訂單信息的就是重復
要求:
對orders映射不能出現重復記錄。在orders.java類中添加List<orderDetail> orderDetails屬性。
最終會將訂單信息映射到orders中,訂單所對應的訂單明細映射到orders中的orderDetails屬性中。
映射成的orders記錄數為兩條(orders信息不重復)
每個orders中的orderDetails屬性存儲了該 訂單所對應的訂單明細
2.4 在orders中添加list訂單明細屬性
2.5 mapper.xml
2.6resultMap定義
2.7 mapper.java
2.8 小結
mybatis使用resultMap的collection對關聯查詢的多條記錄映射到一個list集合屬性中。
使用resultType實現:
將訂單明細映射到orders中的orderdetails中,需要自己處理,使用雙重循環遍歷,去掉重復記錄,將訂單明細放在orderdetails中。
3 多對多查詢
3.1需求:
查詢用戶及用戶購買商品信息。
3.2 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
3.3 映射思路
將用戶信息映射到user中。
在user類中添加訂單列表屬性List<Orders> orderslist,將用戶創建的訂單映射到orderslist
在Orders中添加訂單明細列表屬性List<OrderDetail>orderdetials,將訂單的明細映射到orderdetials
在OrderDetail中添加Items屬性,將訂單明細所對應的商品映射到Items
3.4 mapper.xml
3.5 resultMap定義
3.6 mapper.java
3.7多對多查詢總結:
將查詢用戶購買的商品信息明細清單,(用戶名、用戶地址、購買商品名稱、購買商品時間、購買商品數量)
針對上邊的需求就使用resultType將查詢到的記錄映射到一個擴展的pojo中,很簡單實現明細清單的功能。
一對多是多對多的特例,如下需求:
查詢用戶購買的商品信息,用戶和商品的關系是多對多關系。
需求1:
查詢字段:用戶賬號、用戶名稱、用戶性別、商品名稱、商品價格(最常見)
企業開發中常見明細列表,用戶購買商品明細列表,
使用resultType將上邊查詢列映射到pojo輸出。
需求2:
查詢字段:用戶賬號、用戶名稱、購買商品數量、商品明細(鼠標移上顯示明細)
使用resultMap將用戶購買的商品明細列表映射到user對象中。
總結: 使用resultMap是針對那些對查詢結果映射有特殊要求的功能,,比如特殊要求映射成list中包括 多個list。
4 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集合中。