mybatis高級映射多對多查詢實現

1.同以前一樣,首先給一個使用多對多的需求,

要查詢用戶以及用戶所購買的商品信息,經過分析用戶和商品數據庫級別沒有任何關系,用戶和商品需要建立關系,要通過訂單,訂單明細建立關系。根據這個需求,可以分析出需要查詢的主表為:
查詢主表:用戶表
查詢關聯表:由于商品和用戶沒有關系,通過訂單和訂單明細進行關聯,所以得出關聯表是:orders訂單表,orderDetail訂單明細表,items商品表。這樣的話,sql該如何去寫?這樣寫:

        select
            orders.*,
            t_user.id user_id,
            t_user.address,
            t_user.name,
            t_user.brithday,
            orderdetail.id orderdetail_id,
            orderdetail.orderid,
            orderdetail.itemsid,
            items.id items_id,
            items.name items_name,
            items.price items_price
            from
            orders,
            t_user,
            orderdetail,
            items
            where
            orders.userid=t_user.id AND orderdetail.orderid=orders.id AND orderdetail.itemsId = items.id

為了方便映射,適當加上別名,上面就是寫好的大sql,這sql語句是越來越大了,但不要害怕,待會做映射一個個來做,只要方法得提是很簡單的。
2.編寫映射文件分析:
現在的主表是user,所以將用戶 的信息映射到user中,一個用戶可以創建多個訂單,所以在user屬性中添加List<Orders> orderlist 屬性,這和hibernate越來越像了哈,然后將用戶創建的訂單映射到orderlist,中一個訂單可以包括多個訂單明細,所以在orderS中添加訂單明細列表屬性:List<OrderDetail> orderdetails ,一個訂單明細只包括一個商品信息,所以在OrderSDetail中添加商品items 屬性。


User.java代碼如下:


public class User {
    private int id;
    private String name;
    private String pwd;
    private String address;
    private Date brithday;
    private List<Orders> ordersList;//看這里  用戶創建的訂單列表
  
}

Orders.java代碼如下:

public class Orders {
    private int id;
    private String note;
    private Date dateTime;
    private String number;
    private int userId;
    private User user;
    private List<OrdersDetail> ordersDetails;//一個訂單包括多個訂單明細

OrdersDetail.java代碼如下:

public class OrdersDetail {
    private int id;
    private int orderId;
    private int itemsId;
    private Items items;//一條訂單明細包括一條商品信息

到這里,pojo類之間的關系就搭建好了,接下來寫mapper.xml
代碼如下(注意看代碼里的注釋):

   <!--查詢用戶所購買的商品信息resultMap-->
    <resultMap id="UserAndItemsResultMap" type="com.djp.pojo.User">
        <!--配置用戶信息-->
        <id column="user_id" property="id"/>
        <result column="address" property="address"/>
        <result column="name" property="name"/>
        <result column="brithday" property="brithday"/>
        <!--配置用戶創建的訂單信息,一個用戶創建了多個訂單-->
        <collection property="ordersList" ofType="com.djp.pojo.Orders">
            <id column="id" property="id"/>
            <result column="note" property="note"/>
            <result column="dateTime" property="dateTime"/>
            <result column="userId" property="userId"/>
            <result column="number" property="number"/>
            <!--配置訂單明細信息  一個訂單包含多個訂單明細-->
            <collection property="ordersDetails" ofType="com.djp.pojo.OrdersDetail">
                <id column="orderdetail_id" property="id"/>
                <result column="orderId" property="orderId"/>
                <result column="itemsid" property="itemsId"/>
                <!--配置商品信息  一個明細包括一個商品-->
                <association property="items" javaType="com.djp.pojo.Items">
                    <id column="items_id" property="id"/>
                    <result column="items_name" property="name"/>
                    <result column="items_price" property="price"/>
                </association>
            </collection>
        </collection>
    </resultMap>
    <!--查詢用戶所購買的商品信息-->
    <select id="findUserAndItemsResultMap" resultMap="UserAndItemsResultMap">
        select
            orders.*,
            t_user.id user_id,
            t_user.address,
            t_user.name,
            t_user.brithday,
            orderdetail.id orderdetail_id,
            orderdetail.orderid,
            orderdetail.itemsid,
            items.id items_id,
            items.name items_name,
            items.price items_price
            from
            orders,
            t_user,
            orderdetail,
            items
            where
            orders.userid=t_user.id AND orderdetail.orderid=orders.id AND orderdetail.itemsId = items.id
    </select>

有了之前一對多的映射,類比寫這個就比較簡單了;這里不能使用繼承,因為你發現使用繼承沒法套用了。所以只能老實的寫完。
接下來在接口中添加一個方法,為查詢用戶所購買商品信息

public interface OrdersCustomMapper {
    /**
     * 查詢用戶所購買的商品
     * @return
     * @throws Exception
     */
    List<User> findUserAndItemsResultMap() throws Exception;

最后一步,寫測試類:

  /**findUserAndItemsResultMap
     * 查詢用戶所購買的商品信息
     */
    @Test
    public void testfindUserAndItemsResultMap() {
        try {
            System.out.println("start.................");
            //通過得到的SqlSessionFactory打開回話sqlSession
            SqlSession sqlSession = SqlSessionFactory.openSession();
            //通過會話得到用戶的代理
            OrdersCustomMapper ordersCustomMapper = sqlSession.getMapper(OrdersCustomMapper.class);
            List<User> list = ordersCustomMapper.findUserAndItemsResultMap();
            System.out.println("end.................");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

運行,結果如下:

用戶商品.png

可以看到我展開的列表,是不是想要的數據都出來了;

總結:

到這里可能有人會覺得這個怎么比hibernate中的多對多還麻煩,那么,現在如果有這么一個需求,查詢用戶所購買的商品信息明細清單(用戶名,用戶地址,購買商品名稱,購買商品時間,購買商品數量),這個時候應該使用resultMap還是resulType,這個時候會發現,針對上面的需求,就是用resultType將查詢到的信息映射到一個擴展的pojo中,很好用,加屬性就行了,這樣的話就可以很簡單地實現明細清單的功能,比如話費賬單,張三幾點幾分給誰打電話,張三幾點幾分打電話給誰,沒必要去重復記錄。所以,要根據需求來,并非所有的一對多都是上面的resultMap那種查詢。使用resultMap是針對那些查詢結果有特殊要求的功能,比如映射成list中還包括多個list。
一對多是多對多的特咧:查詢用戶購買商品信息,用戶和商品是多對多關系。
需求1:查詢字段:用戶賬號,用戶名稱,用戶性別,商品名稱,商品價格(最常見)。企業開發中常見的明細表,用戶購買商品明細表等。
方法:使用resultType將上面商品輸出
需求2:查詢字段:用戶賬號,用戶名稱,購買商品數量,商品明細(鼠標移動到上面顯示明細)
方法:使用resultMap將用戶所購買的商品明細映射到user中。

對resultMap的大總結:

resultType:
作用:將查詢結果按照sql列名和pojo屬性名一致映射到pojo中
場合:常見的一些明細記錄的展示,比如用戶購買商品的明細,將關聯查詢的信息全部展示在頁面時,此時用resultType將每一條記錄映射到pojo中,在前端頁面遍歷list即可。
resultMap:
使用association和collection完成一對一和一對多的高級映射(對結果有特殊要求)。
association:
作用:將關聯查詢的信息映射到一個pojo中
場合:為了方便查詢關聯信息可以使用association將關聯訂單信息映射為用戶對象的pojo屬性中,比如:查詢訂單關聯查詢用戶信息。
collection:
作用:將關聯查詢用戶信息映射到一個list集合中
場合:為了方便查詢遍歷關聯信息可以使用collection將關聯信息映射到list集合中,比如:查詢用戶權限范圍模塊以及模塊下的菜單,可以使用collection將模塊映射到list中,將菜單列表遍歷即可!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容