前言
當我們學習heribnate的時候,也就是SSH框架的網上商城的時候,我們就學習過它對應的高級映射,一對一映射,一對多映射,多對多映射。對於SSM的Mybatis來說,肯定也是差不多的。既然開了頭了,我們就也來簡單說一些Mybatis的高級映射。當然說到這些東西的時候,最簡單也最常用的就是級聯查詢,所以我們就以幾個簡單的級聯查詢為例,分別說一下Mybatis的一對一、一對多、多對多查詢。
一、一對一映射
1、需求:
電商類做買賣,用戶提交訂單后,某寶根據訂單信息和客戶的姓名、地址派送,現在查詢所有的訂單信息,關聯查詢下但用戶信息。
(1)首先確定執行的sql語句為:
- <span style="font-size:18px;">SELECT orders.*,user.username,userss.address FROM orders,user WHEREorders.user_id = user.id</span>
resultType方式解決這個問題:
(1)定義po類:
- public class OrdersCustom extends Orders {
- 段,只需要定義用戶的信息字段即可。
-
- private String username;
- private String address;
- public String getUsername(){
- return username;
- }
- public String setUsername(String username){
- this.username=username;
- }
- ……
- }
(2)Mapper映射文件:
- <select id="findOrdersList" resultType="cn.itcast.mybatis.po.OrdersCustom">
- SELECT
- orders.*,
- user.username,
- user.address
- FROM
- orders, user
- WHERE orders.user_id = user.id
- </select>
(3)定義mapper接口:
- <span style="font-size:18px;">public List<OrdersCustom> findOrdersList() throws Exception;</span>
(4)測試:
- Public void testfindOrdersList()throws Exception{
-
- SqlSession session = sqlSessionFactory.openSession();
-
- UserMapper userMapper = session.getMapper(UserMapper.class);
-
- List<OrdersCustom> list =userMapper.findOrdersList();
- System.out.println(list);
-
- session.close();
- }
使用resultMap解決問題:
(1)定義resultMap:
- <resultMap type="cn.itcast.mybatis.po.Orders"id="userordermap">
- <id property="id" column="id"/>
- <resultpropertyresultproperty="user_id" column="user_id"/>
- <resultpropertyresultproperty="number" column="number"/>
- <associationpropertyassociationproperty="user" javaType="cn.itcast.mybatis.po.User">
- <id property="id" column="user_id"/>
- <resultpropertyresultproperty="username" column="username"/>
- <resultpropertyresultproperty="address" column="address"/>
- </association>
- </resultMap>
(2)調用resultMap:
- <select id="findOrdersListResultMap" resultMap="userordermap">
- SELECT
- orders.*,
- user.username,
- user.address
- FROM
- orders, user
- WHERE orders.user_id = user.id
- </select>
(3)定義mapper接口
一對一查詢總結:
個人認為啊,這種情況下使用resultType定義輸出映射相對簡單,因為這樣只需要去添加一個po類就行了,按需求添加額外需要的屬性,就可以完成映射。而相對於resultType來說,resultMap就顯得稍微麻煩一些了,他需要特別定義resultMap來映射相關聯表的實體屬性。
二、一對多查詢:
1、需求:
繼上面的需求,查詢所有訂單信息及訂單下的訂單明細信息(一個訂單信息下面或有很多商品,這個女生買護膚品的時候應該很有感觸吧。所以訂單信息與訂單明細是一對多的關系)
(1)確定在數據庫執行的sql語句:
- Select orders.*, user.username, user.address,orderdetail.idorderdetail_id,orderdetail.items_id,
- orderdetail.items_num FROM orders,user,orderdetail
- WHERE orders.user_id = user.id AND orders.id = orderdetail.orders_id
執行結果:

(2)定義po類:
- public class Orders{
- private Integer id;
- private Integer userId;
- private String number;
- private Date createtime;
- private String note;
- private User user;
- private List<OrderDetial> orderDetails;
-
- }
(3)定義resultMap
- <resultMaptyperesultMaptype="cn.itcast.mybatis.po.Orders"id="userorderdetailmap">
- <id property="id"column="id"/>
- <result property="user_id" column="user_id"/>
- <result property="number" column="number"/>
- <association property="user" javaType="cn.itcast.mybatis.po.User">
- <id property="id" column="user_id"/>
- <result property="username" column="username"/>
- <result property="address" column="address"/>
- </association>
- <collectionpropertycollectionproperty="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
- <id property="id" column="orderdetail_id"/>
- <result property="items_id" column="items_id"/>
- <result property="items_num" column="items_num"/>
- </collection>
- </resultMap>
大家可以跟上面對比一下,這兩個resultMap除了對訂單詳細的映射定義外,其他的是完全一樣的,現在問題來了,我們需要重新定義上面重復的映射信息嗎?答案是不用,resultMap具有可繼承特性,我們只需要繼承上面的resultMap(userordermap),然后只定義別的就可以了,如下:
- <resultMaptyperesultMaptype="cn.itcast.mybatis.po.Orders" id="userorderdetailmap" extends="userordermap">
- <collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
- <id property="id" column="orderdetail_id"/>
- <result property="items_id" column="items_id"/>
- <result property="items_num" column="items_num"/>
- </collection>
- </resultMap>
使用extends來繼承訂單信息resultmap:userordermap
(4)實現調用:
- <selectidselectid="findOrdersDetailList" resultMap="userorderdetailmap">
- SELECT
- orders.*,
- user.username,
- user.address,
- orderdetail.id orderdetail_id,
- orderdetail.items_id,
- orderdetail.items_num
- FROM orders,user,orderdetail
- WHERE orders.user_id = user.id
- AND orders.id =orderdetail.orders_id
- </select>
(5)定義mapper接口:
- publicList<Orders>findOrdersDetailList () throws Exception;
(6)來測試一下:
- Public void testfindOrdersDetailList()throws Exception{
-
- SqlSession session = sqlSessionFactory.openSession();
-
- UserMapper userMapper =session.getMapper(UserMapper.class);
-
- List<Orders> list =userMapper.findOrdersDetailList();
- System.out.println(list);
-
- session.close();
- }
這個吧,圖沒有了,可是可以給大家形容一下,就是返回結果只有四個訂單信息,然后每個訂單信息里面有兩個商品信息list壓到這里面。就這樣,我們就實現了一對多的查詢,為什么這個例子我們不用resultType來執行,其實結果早就給大家了,上面執行sql的結果圖,就是返回的信息列表,實際上只有四個訂單信息,但是使用resultType會返回8條信息,也就是沒有完成去重,還需要我們去手動去重,了然了嗎?不是很方便
三、多對多查詢
(1)需求:
查詢用戶購買的商品信息(一個用戶可以有N個訂單信息,每個訂單信息可以有M個商品信息,所以我們需要查詢所有的用戶信息,關聯查詢訂單及訂單明細信息,訂單名信息中關聯查詢商品信息)
(2)確定要執行的sql:
- SELECT
- orders.*,
- USER.username,
- USER.address,
- orderdetail.idorderdetail_id,
- orderdetail.items_id,
- orderdetail.items_num,
- items.nameitems_name,
- items.detailitems_detail
- FROM
- orders,
- USER,
- orderdetail,
- items
- WHERE
- orders.user_id= USER .id
- AND orders.id = orderdetail.orders_id
- ANDorderdetail.items_id = items.id
(3)po類變化:
在User中添加List<Orders>orders 屬性;在Orders類中加入List<Orderdetail> orderdetails屬性;Items類,不用動
(4)定義resultMap:
- <resultMap type="cn.itcast.mybatis.po.User"id="userOrderListResultMap">
- <id column="user_id"property="id"/>
- <result column="username"property="username"/>
- <collection property="orders"ofType="cn.itcast.mybatis.po.Orders">
- <id column="id"property="id"/>
- <result property="number" column="number"/>
- <collection property="orderdetails"ofType="cn.itcast.mybatis.po.Orderdetail">
- <id column="orderdetail_id" property="id"/>
- <result property="ordersId"column="id"/>
- <result property="itemsId"column="items_id"/>
- <result property="itemsNum"column="items_num"/>
- <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"/>
- </association>
- </collection>
- </collection>
- </resultMap>
(5)調用resultMap:
- <select id="findUserItemResultMap" resultMap="UserItemResultMap" >
- select orders.*,
- user.username,
- user.sex,
- user.address,
- orderdetail.id,
- orderdetail_id,
- orderdetail.items_id,
- orderdetail.items_num,
- orderdetail.orders_id,
- item.id item_id,
- item.name item_name,
- item.detail item_detail,
- item.price item_price
- from orders,user,orderdetail,item
- where orders.user_id=user.id
- and orders.id=orderdetail.orders_id
- and orderdetail.items_id=item.id
- </select>
到這里,相信大家能看出點端倪來了吧,我們一直都是用<collection></collection>和<association></association>分別對集合和實體進行關聯映射,而且它們層層嵌套的方式就跟實體之間層層嵌套的方式一樣:user中包含orders,orders中包含orderdetail,orderdetail中包含item。
(6)然后定義mapper接口:
- public interface UserMapper { List<User> findUserItemResultMap() throws Exception;}
結果,就請大家自己去動手實驗一下吧!
到此,我們的Mybatis高級映射之一對一,一對多,多對多映射就分享完了,期間自己又有點收獲,總結一下:
1、resultType:將查詢結果按照sql列名pojo屬性名一致性映射到pojo中。常見一些明細記錄的展示,比如用戶購買商品明細,將關聯查詢信息全部展示在頁面時,此時可直接使用resultType將每一條記錄映射到pojo中,在前端頁面遍歷list(list中是pojo)即可。
2、resultMap:使用association和collection完成一對一和一對多高級映射(對結果有特殊的映射要求)。其中association見關聯查詢信息映射到一個pojo對象中,collection將關聯查詢信息映射到一個list集合中然而,使用resultType無法將查詢結果映射到pojo對象的pojo屬性中,根據對結果集查詢遍歷的需要選擇使用resultType還是resultMap。那就要看我們自己的判斷力了。