1. 程式人生 > >MyBatis一對多查詢(使用resultMap)

MyBatis一對多查詢(使用resultMap)

【需求】

查詢訂單以及訂單明細的資訊。

確定主查詢表:訂單表orders

確定關聯查詢表:訂單明細表 orderdetail

在一對一查詢的基礎上新增訂單明細表關聯即可。

【分析】

使用resultMap將上面的查詢結果對映到pojo中,訂單資訊有重複。

要求:對orders對映不能出現重複記錄

在orders.java類中新增List<orderDetail> orderDetails屬性。

最終會將訂單資訊對映到orders中,訂單所對應的訂單明細對映到orders中的orderDetails屬性中。如下所示:

對映成的orders記錄為兩條(orders資訊不能重複)

每個orders中的orderDetails屬性儲存了該訂單所對應的訂單明細。

 【工程截圖】

【User.java】

package cn.higgin.mybatis.po;

import java.util.Date;

public class User {
    //屬性名和資料庫表的欄位對應
    private int id;
    private String username;
    private String sex;
    private Date birthday;
    private String address;
    //set/get方法忽略.....
}

【Orderdetail.java】

package cn.higgin.mybatis.po;

public class Orderdetail {
    private Integer id;

    private Integer ordersId;

    private Integer itemsId;

    private Integer itemsNum;
    //get/set方法忽略......
}

【Orders.java】

package cn.higgin.mybatis.po;
import java.util.Date;
import java.util.List;

public class Orders {
    
    private Integer id;
    private Integer userId;
    private String number;
    private Date createtime;
    private String note;
    //引入使用者資訊
    private User user;
    //引入訂單明細(和上面的使用者資訊不同,一個是一對一,一個是一對多)
    private List<Orderdetail> orderdetails; //注意是orderdetails,一個有's',一個有's'
    //忽略set/get方法......
}

【OrdersMapperCustom.java】

package cn.higgin.mybatis.mapper;

import java.util.List;

import cn.higgin.mybatis.po.Orders;

public interface OrdersMapperCustom {
    
    //查詢訂單(關聯使用者)及訂單明細
    public List<Orders> findOrdersAndOrderDetailResultMap() throws Exception;
}

【OrdersMapperCustomer.xml】

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="cn.higgin.mybatis.mapper.OrdersMapperCustom">
    
    <!--
         訂單查詢關聯使用者的resultMap
        將整個查詢的結果對映到cn.higgin.mybatis.po.Orders中
     -->
     <resultMap type="cn.higgin.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.higgin.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>
    
    
    <!-- 訂單及訂單明細的resultType 
        使用extends繼承OrdersUserResultMap中的資訊,無需在其中配置訂單和使用者的資訊
    -->
    <resultMap type="cn.higgin.mybatis.po.Orders" id="OrdersAndOrderDetailResultMap"
        extends="OrdersUserResultMap">
        <!-- 1.訂單資訊(從繼承的OrdersUserResultMap中獲取) -->
        
        <!-- 2.使用者資訊(從繼承的OrdersUserResultMap中獲取) -->
        
        <!-- 訂單明細資訊
            一個訂單關聯查詢出了多條明細,要使用collection進行對映
            collection:對關聯查詢到多條記錄對映到集合物件中
            property: 將關聯查詢到多條記錄對映到cn.higgin.mybatis.po.Orders的對應屬性
            ofType: 指定對映到list集合屬性中pojo的型別,在[Orders.java]中的 private List<Orderdetail> orderdetails;
         -->
         <collection property="orderdetails" ofType="cn.higgin.mybatis.po.Orderdetail">
             <!-- id:訂單明細唯一標識
                 property:要將訂單明細的唯一標識對映到cn.higgin.mybatis.po.Orderdetail的對應屬性 -->
             <id column="orderdetail_id" property="id"/>
             <result column="items_id" property="id"/>
             <result column="items_num" property="itemsNum"/>
             <result column="orders_id" property="ordersId"/>
         </collection>
    </resultMap>
    
    <!-- 查詢訂單關聯查詢使用者資訊,使用resultMap -->
    <select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDetailResultMap">
        SELECT
            orders.*,
            USER.username,
            USER.sex,
            USER.address,
            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
    </select> 
    
</mapper>

【OrdersMapperCustomTest.java】

package cn.higgin.mybatis.mapper;

import java.io.InputStream;
import java.util.List;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;

import cn.higgin.mybatis.po.Orders;

public class OrdersMapperCustomTest {
    private SqlSessionFactory sqlSessionFactory;

    // 此方法是在執行testFindUserById之前執行
    @Before
    public void setUp() throws Exception {
        // 建立sqlSessionFactory

        // mybatis配置檔案
        String resource = "SqlMapConfig.xml";
        // 得到配置檔案流
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 建立會話工廠,傳入mybatis的配置檔案資訊
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void testFindOrdersUser() throws Exception {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        //建立代理物件
        OrdersMapperCustom ordersMapperCustom=sqlSession.getMapper(OrdersMapperCustom.class);
        
        //呼叫mapper的方法
        List<Orders> list=ordersMapperCustom.findOrdersAndOrderDetailResultMap();
        
        System.out.println(list.size());
        
        sqlSession.close();
    }
}

【debug執行結果】

可見只有兩條記錄:

再檢視一下具體內容:

注意:重複的資料被合併,不重複的資料在集合中,下圖作對比:

【小結】

mybatis使用resultMap的collection對關聯查詢的多條記錄對映對映到一個list集合屬性中(private List<Orderdetail> orderdetails;)。

使用resultType也可以實現:

將訂單明細對映到orders中的orderdetails中,需要自己處理,使用雙重迴圈遍歷,去掉重複記錄,將訂單明細放在orderdetails中。