Mybatis學習總結(六)——高級映射(一對一,一對多,多對多)


一、訂單商品數據模型

1、數據庫執行腳本

創建數據庫表代碼:

/*Table structure for table `t_user` */
CREATE TABLE t_user (
  id INT NOT NULL AUTO_INCREMENT,
  username VARCHAR(32) NOT NULL COMMENT '用戶名稱',
  birthday DATE DEFAULT NULL COMMENT '生日',
  sex CHAR(1) DEFAULT NULL COMMENT '性別',
  address  VARCHAR(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;

/*Table structure for table `items` */
CREATE TABLE items (
  id INT NOT NULL  AUTO_INCREMENT,
  itemsname VARCHAR(32) NOT NULL COMMENT '商品名稱',
  price FLOAT(10,1) NOT NULL COMMENT '商品定價',
  detail TEXT COMMENT '商品描述',
  pic VARCHAR(64) DEFAULT NULL COMMENT '商品圖片',
  createtime DATETIME NOT NULL COMMENT '生產日期',
  PRIMARY KEY (id)
)  DEFAULT CHARSET=utf8;

/*Table structure for table `orders` */
CREATE TABLE orders (
  id INT NOT NULL AUTO_INCREMENT,
  user_id INT NOT NULL COMMENT '下單用戶id',
  number VARCHAR(30) NOT NULL COMMENT '訂單號',
  createtime DATETIME NOT NULL COMMENT '創建訂單時間',
  note VARCHAR(100) DEFAULT NULL COMMENT '備注',
  PRIMARY KEY (`id`),
  KEY `FK_orders_1` (`user_id`),
  CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
)  DEFAULT CHARSET=utf8;

/*Table structure for table `orderdetail` */
CREATE TABLE orderdetail (
  id INT NOT NULL AUTO_INCREMENT,
 orders_id INT NOT NULL COMMENT '訂單id',
  items_id INT NOT NULL COMMENT '商品id',
  items_num INT  DEFAULT NULL COMMENT '商品購買數量',
  PRIMARY KEY (id),
  KEY `FK_orderdetail_1` (`orders_id`),
  KEY `FK_orderdetail_2` (`items_id`),
  CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
)  DEFAULT CHARSET=utf8;

測試數據:

/*Data for the table `user` */
INSERT  INTO `t_user`(`username`,`birthday`,`sex`,`address`) VALUES 
('王五',NULL,'2',NULL),
('張三','2014-07-10','1','北京市'),
('張小明',NULL,'1','河南鄭州'),
('陳小明',NULL,'1','河南鄭州'),
('張三豐',NULL,'1','河南鄭州'),
('陳小東',NULL,'1','河南鄭州'),
('王五',NULL,NULL,NULL),
 ('小A','2015-06-27','2','北京'),
('小B','2015-06-27','2','北京'),
('小C','2015-06-27','1','北京'),
('小D','2015-06-27','2','北京');

/*Data for the table `items` */
INSERT  INTO items(itemsname,price,detail,pic,createtime) VALUES 
('台式機',3000.0,'該電腦質量非常好!',NULL,'2015-07-07 13:28:53'),
('筆記本',6000.0,'筆記本性能好,質量好!',NULL,'2015-07-08 13:22:57'),
('背包',200.0,'名牌背包,容量大質量好!',NULL,'2015-07-010 13:25:02');

/*Data for the table `orders` */
INSERT  INTO `orders`(`user_id`,`number`,`createtime`,`note`) VALUES 
(1,'1000010','2015-06-04 13:22:35',NULL),
(1,'1000011','2015-07-08 13:22:41',NULL),
(2,'1000012','2015-07-17 14:13:23',NULL),
(3,'1000013','2015-07-16 18:13:23',NULL),
(4,'1000014','2015-07-15 19:13:23',NULL),
(5,'1000015','2015-07-14 17:13:23',NULL),
(6,'1000016','2015-07-13 16:13:23',NULL);

/*Data for the table `orderdetail` */
INSERT  INTO `orderdetail`(`orders_id`,`items_id`,`items_num`) VALUES
 (1,1,1),
 (1,2,3),
 (2,3,4),
 (3,2,3);

2、數據模型分析思路

(1).每張表記錄的數據內容:分模塊對每張表記錄的內容進行熟悉,相當於你學習系統需求(功能)的過程;

(2).每張表重要的字段設置:非空字段、外鍵字段;

(3).數據庫級別表與表之間的關系:外鍵關系;

(4).表與表之間的業務關系:在分析表與表之間的業務關系時一定要建立在某個業務意義基礎上去分析。

3、針對訂單商品模型的數據庫思路分析:

用戶表:t_user-->記錄了購買商品的用戶信息

訂單表:orders-->記錄了用戶所創建的訂單(購買商品的訂單)

訂單明細表:orderdetail-->記錄了訂單的詳細信息即購買商品的信息

商品表:items-->記錄了商品信息

表與表之間的業務關系:

  在分析表與表之間的業務關系時需要建立 在某個業務意義基礎上去分析。

  先分析數據級別之間有關系的表之間的業務關系:

t_userorders

  t_user---->orders:一個用戶可以創建多個訂單,一對多

  orders--->t_user:一個訂單只由一個用戶創建,一對一

orders和orderdetail

  orders--->orderdetail:一個訂單可以包括多個訂單明細,因為一個訂單可以購買多個商品,每個商品的購買信息在orderdetail記錄,一對多關系

  orderdetail--> orders:一個訂單明細只能包括在一個訂單中,一對一

orderdetail和items

  orderdetail--->itesms:一個訂單明細只對應一個商品信息,一對一

  items--> orderdetail:一個商品可以包括在多個訂單明細 ,一對多

再分析數據庫級別沒有關系的表之間是否有業務關系:

orders和items

  ordersitems之間可以通過orderdetail表建立關系。

4、分析之后畫出對應的圖,方便直觀的了解業務關系

二、一對一查詢

2.1、需求:查詢訂單信息,關聯查詢用戶信息。

2.2、resultType實現

2.2.1、sql語句   

   確定查詢的主表:訂單表,確定查詢的關聯表:用戶表。

SELECT    t1.*,t2.username,t2.sex,t2.address
FROM  orders t1,t_user t2
WHERE t1.user_id=t2.id

2.2.2、創建entity實體

用戶實體:User.java

package com.mybatis.entity;

import java.util.Date;
import java.util.List;

/**
 * @ClassName: User
 * @Description: TODO(用戶實體)
 * @author lixiaoxi
 * @date 2015-6-27 下午1:56:02
 * 
 */
public class User {
    // 屬性名稱和數據庫字段名稱保持一致
    private Integer id;
    // 姓名
    private String username;
    // 性別
    private String sex;
    // 地址
    private String address;
    // 生日
    private Date birthday;
    // 用戶創建的訂單列表
    private List<Orders> ordersList;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    
    public List<Orders> getOrdersList() {
        return ordersList;
    }

    public void setOrdersList(List<Orders> ordersList) {
        this.ordersList = ordersList;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", sex=" + sex
                + ", address=" + address + ", birthday=" + birthday + "]";
    }

}

訂單實體:Orders.java

package com.mybatis.entity;

import java.util.Date;
import java.util.List;

/**
 * @ClassName: Orders
 * @Description: TODO(訂單實體)
 * @author lixiaoxi 
 */
public class Orders {
    
    /** 主鍵訂單Id */
    private Integer id;
    /** 下單用戶id */
    //private Integer userid;
    /** 訂單號 */
    private String number;
    /** 創建訂單時間 */
    private Date createTime;
    /** 備注 */
    private String note;
    // 用戶信息
    private User user;
    // 訂單明細
    private List<OrderDetail> orderdetails;
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
//    public Integer getUserid() {
//        return userid;
//    }
//    public void setUserid(Integer userid) {
//        this.userid = userid;
//    }
    public String getNumber() {
        return number;
    }
    public void setNumber(String number) {
        this.number = number;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public List<OrderDetail> getOrderdetails() {
        return orderdetails;
    }
    public void setOrderdetails(List<OrderDetail> orderdetails) {
        this.orderdetails = orderdetails;
    }

}

商品實體:Items.java

package com.mybatis.entity;

import java.util.Date;

/**
 * @ClassName: Items
 * @Description: TODO(商品實體類)
 * @author lixiaoxi 
 */
public class Items {
    
    /** 商品表主鍵Id */
    private Integer id;
    /** 商品名稱 */
    private String itemsName;
    /** 商品定價 */
    private float price;
    /** 商品描述 */
    private String detail;
    /** 商品圖片 */
    private String picture;
    /** 生產日期 */
    private Date createTime;
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getItemsName() {
        return itemsName;
    }
    public void setItemsName(String itemsName) {
        this.itemsName = itemsName;
    }
    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
    public String getDetail() {
        return detail;
    }
    public void setDetail(String detail) {
        this.detail = detail;
    }
    public String getPicture() {
        return picture;
    }
    public void setPicture(String picture) {
        this.picture = picture;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

}

訂單明細實體:OrderDetail.java

package com.mybatis.entity;

/**
 * @ClassName: OrderDetail
 * @Description: TODO(訂單明細實體)
 * @author lixiaoxi 
 */
public class OrderDetail {

    /** 主鍵,訂單明細表Id */
    private Integer id;
    /** 訂單Id */
    private Integer ordersId;
    /** 商品id */
    private Integer itemsId;
    /** 商品購買數量 */
    private Integer itemsNum;
    // 明細對應的商品信息
    private Items items;
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getOrdersId() {
        return ordersId;
    }
    public void setOrdersId(Integer ordersId) {
        this.ordersId = ordersId;
    }
    public Integer getItemsId() {
        return itemsId;
    }
    public void setItemsId(Integer itemsId) {
        this.itemsId = itemsId;
    }
    public Integer getItemsNum() {
        return itemsNum;
    }
    public void setItemsNum(Integer itemsNum) {
        this.itemsNum = itemsNum;
    }
    public Items getItems() {
        return items;
    }
    public void setItems(Items items) {
        this.items = items;
    }
}

創建一個包裝類,將查詢到的信息可以全部映射到此類:OrdersCustom.java 

/**
 * @ClassName: OrdersCustom
 * @Description: TODO(訂單的擴展類,通過此類映射訂單和用戶的查詢結果,讓此類繼承字段較多的實體類)
 * @author: 阿赫瓦里
 */
public class OrdersCustom extends Orders {
    // 添加用戶的屬性
    private String username;
    private String sex;
    private String address;
        // getter and setter......
}

2.2.3、創建OrdersCustomMapper.java

package com.mybatis.mapper;

import java.util.List;
import com.mybatis.entity.OrdersCustom;

public interface OrdersCustomMapper {
    
    /** 查詢訂單,關聯查詢用戶信息 */
    public List<OrdersCustom> findOrdersUser();

}

 2.2.4、創建OrdersCustomMapper.xml和上面對應的接口名稱一致,以便通過mapper接口加載配置文件

<?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="com.mybatis.mapper.OrdersCustomMapper">

    <!-- 查詢訂單,關聯查詢用戶信息 -->
    <select id="findOrdersUser" resultType="com.mybatis.entity.OrdersCustom">
        select t1.*,t2.username,t2.sex,t2.address from orders t1,t_user t2
        where t1.user_id = t2.id
    </select>
    
</mapper>

2.3、resultMap實現

2.3.1、sql語句同上

2.3.2、resultMap映射思路:

使用resultMap將查詢結果中的訂單信息映射到Orders對象中,在orders類中添加User屬性,將關聯查詢出來的用戶信息映射到orders對象中的user屬性中(上面orders實體中已經添加)。

2.3.3、ordersCustomMapper.xml

1、定義resultMap

<!-- 定義查詢訂單關聯用戶的 resultMap,將整個的查詢結果映射到com.mybatis.entity.Orders中 -->
<resultMap type="com.mybatis.entity.Orders" id="OrdersUserResultMap">
    <!-- 1.配置映射的訂單信息 -->
    <!-- id:查詢列中的唯一標識,訂單信息中的唯一標識,如果多列組成唯一標識(如:一般數據庫設計中的字典表 使用聯合主鍵),
        就需要配置多個id. 
        column:訂單信息的唯一標識 列
        property:訂單信息的唯一標識列所映射到orders中的那個屬性(假如:數據庫中orders表中的主鍵為orders_id,而實體屬性名稱
            為ordersId,則這個配置應為<id column="orders_id" property="ordersId"/>,類似hibernate實體映射文件配置)。
    -->
    <id column="id" property="id"/>
    <result column="number" property="number"/>
    <result column="createtime" property="createTime"/>
    <result column="note" property="note"/>
    
    <!-- 2.配置映射的關聯用戶信息 -->
    <!--association:用於映射關聯查詢單個對象的信息
        property:要將關聯查詢的用戶信息映射到Orders中那個屬性
      -->
    <association property="user" javaType="com.mybatis.entity.User">
        <!-- id:關聯查詢用戶的唯一標識 
            column:指定唯一標識用戶信息的列
            property:映射到user的那個屬性
        -->
        <id column="user_id" property="id"/>
        <result column="username" property="username"/>
        <result column="sex" property="sex"/>
        <result column="address" property="address"/>
    </association>

</resultMap>

2、statement定義

<!-- 查詢訂單,關聯查詢用戶信息,使用resultMap實現 -->
<select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap">
    SELECT t1.*,t2.username,t2.sex,t2.address FROM orders t1,t_user t2
    WHERE t1.user_id=t2.id
</select>

3、OrdersCustomMapper.java接口中添加下面的方法

 /** 查詢訂單關聯查詢用戶信息,使用reslutMap實現*/
public List<Orders>findOrdersUserResultMap();

4、對resultType和resultMap實現的一對一查詢進行Junit測試:

package com.mybatis.test;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
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 com.mybatis.entity.OrderDetail;
import com.mybatis.entity.Orders;
import com.mybatis.entity.OrdersCustom;
import com.mybatis.mapper.OrdersCustomMapper;

public class OrdersCustomMapperTest {
    
    private SqlSessionFactory sqlSessionFactory;
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
    // 此方法是在執行@Test方法之前執行
    @Before
    public void setUp() throws Exception {
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 創建SqlSessionFcatory
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    // 查詢訂單,關聯查詢用戶信息,使用resultType實現的測試
    @Test
    public void TestFindOrdersUser() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 創建代理對象
        OrdersCustomMapper oc = sqlSession.getMapper(OrdersCustomMapper.class);
        // 調用mapper的方法
        List<OrdersCustom> list = oc.findOrdersUser();
        if(list !=null && list.size()>0){
            System.out.println("一對一使用resultType實現:");
            for(int i=0;i<list.size();i++){
                OrdersCustom entity = (OrdersCustom)list.get(i);
                System.out.println("訂單id:"+entity.getId()+"----訂單號:"+entity.getNumber()+
                        "----創建時間:"+DATE_FORMAT.format(entity.getCreateTime())+"----用戶:"+entity.getUsername());
                
            }
        }
        //System.out.println(list);
        sqlSession.close();
    }
    
    // 查詢訂單,關聯查詢用戶信息,使用resultMap實現的測試
    @Test
    public void TestFindOrdersUserResultMap() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 創建代理對象
        OrdersCustomMapper oc = sqlSession.getMapper(OrdersCustomMapper.class);
        // 調用mapper的方法
        List<Orders> list = oc.findOrdersUserResultMap();
        if(list !=null && list.size()>0){
            System.out.println("\n一對一使用resultMap實現:");
            for(int i=0;i<list.size();i++){
                Orders entity = (Orders)list.get(i);
                System.out.println("訂單id:"+entity.getId()+"----訂單號:"+entity.getNumber()+
                        "----創建時間:"+DATE_FORMAT.format(entity.getCreateTime())+
                        "----用戶id:"+entity.getUser().getId()+
                        "----用戶名:"+entity.getUser().getUsername());
                
            }
        }
        System.out.print("\n");
        sqlSession.close();
    }
    
}

運行結果:

一對一使用resultType實現:
訂單id:1----訂單號:1000010----創建時間:2015-06-04 13:22:35----用戶:王五
訂單id:2----訂單號:1000011----創建時間:2015-07-08 13:22:41----用戶:王五
訂單id:3----訂單號:1000012----創建時間:2015-07-17 14:13:23----用戶:張三
訂單id:4----訂單號:1000013----創建時間:2015-07-16 18:13:23----用戶:張小明
訂單id:5----訂單號:1000014----創建時間:2015-07-15 19:13:23----用戶:陳小明
訂單id:6----訂單號:1000015----創建時間:2015-07-14 17:13:23----用戶:張三豐
訂單id:7----訂單號:1000016----創建時間:2015-07-13 16:13:23----用戶:陳小東

一對一使用resultMap實現:
訂單id:1----訂單號:1000010----創建時間:2015-06-04 13:22:35----用戶id:1----用戶名:王五
訂單id:2----訂單號:1000011----創建時間:2015-07-08 13:22:41----用戶id:1----用戶名:王五
訂單id:3----訂單號:1000012----創建時間:2015-07-17 14:13:23----用戶id:2----用戶名:張三
訂單id:4----訂單號:1000013----創建時間:2015-07-16 18:13:23----用戶id:3----用戶名:張小明
訂單id:5----訂單號:1000014----創建時間:2015-07-15 19:13:23----用戶id:4----用戶名:陳小明
訂單id:6----訂單號:1000015----創建時間:2015-07-14 17:13:23----用戶id:5----用戶名:張三豐
訂單id:7----訂單號:1000016----創建時間:2015-07-13 16:13:23----用戶id:6----用戶名:陳小東

5、resultTyperesultMap實現一對一查詢小結

實現一對一查詢:

a.resultType:使用resultType實現較為簡單,如果pojo中沒有包括查詢出來的列名,需要增加列名對應的屬性,即可完成映射。

b.如果沒有查詢結果的特殊要求建議使用resultType

c.resultMap:需要單獨定義resultMap,實現有點麻煩,如果對查詢結果有特殊的要求,使用resultMap可以完成將關聯查詢映射pojo的屬性中。

d.resultMap可以實現延遲加載,resultType無法實現延遲加載。

三、一對多查詢

3.1、需求:查詢訂單(關聯用戶)及訂單明細;

3.2、在orders.java類中添加List<orderDetail> orderDetails屬性(上面實體已添加)

最終會將訂單信息映射到orders中,訂單所對應的訂單明細映射到orders中的orderDetails屬性中.

3.3、在ordersCustomMapper.xml中添加如下代碼

1、定義resultMap

<!-- 查詢訂單(關聯用戶)及訂單明細的resultMap -->
<resultMap type="com.mybatis.entity.Orders" id="ordersAndOrderDetailResultMap" extends="OrdersUserResultMap">
    <!-- 訂單信息 -->
    <!-- 關聯用戶信息 -->
    <!-- 使用extends繼承,不用再配置訂單信息和用戶信息的映射-->
    
     <!-- 關聯訂單明細信息 , 一個訂單關聯查詢出了多條訂單明細,要使用collection映射
        collection:對關聯查詢到的多條記錄映射到集合中
        property:將關聯查詢到的多條記錄映射到orders類的那個屬性
        ofType:指定映射的集合屬性中pojo的類型
    -->
    <collection property="orderdetails" ofType="com.mybatis.entity.OrderDetail">
        <!-- id:唯一標識
             property:要將訂單明細的唯一標識映射到com.mybatis.entity.OrderDetail的那個屬性
         -->
        <id column="orderdetail_id" property="id"/>
        <result column="items_id" property="itemsId"/>
        <result column="items_num" property="itemsNum"/>
        <result column="orders_id" property="ordersId"/>
    </collection>
</resultMap>

2、statement定義

<!-- 查詢訂單關聯查詢用戶及訂單明細 -->
<select id="findOrdersAndOrderDetailResultMap" resultMap="ordersAndOrderDetailResultMap">
    SELECT t1.*,t2.username,t2.sex,t2.address,t3.id orderdetail_id,t3.items_id,
    t3.items_num,t3.orders_id FROM orders t1,t_user t2,orderdetail t3
    WHERE t1.user_id = t2.id AND t3.orders_id=t1.id
</select>

3.4、在OrdersCustomMapper.java接口類中添加一個方法

/**查詢訂單(關聯用戶)以及訂單明細*/
public List<OrderDetail>findOrdersAndOrderDetailResultMap();

3.5、在Junit測試類中添加測試方法

// 查詢訂單(關聯用戶)以及訂單明細的測試
@Test
public void TestFindOrdersAndOrderDetailResultMap() {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    // 創建代理對象
    OrdersCustomMapper oc = sqlSession.getMapper(OrdersCustomMapper.class);
    // 調用mapper的方法
    List<Orders> list = oc.findOrdersAndOrderDetailResultMap();
    if(list !=null && list.size()>0){
        System.out.println("一對多測試:");
        for(int i=0;i<list.size();i++){
            System.out.println("訂單關聯用戶信息:");
            Orders entity = (Orders)list.get(i);
            System.out.println("訂單id:"+entity.getId()+"----訂單號:"+entity.getNumber()+
                    "----創建時間:"+DATE_FORMAT.format(entity.getCreateTime())+
                    "----用戶id:"+entity.getUser().getId()+
                    "----用戶名:"+entity.getUser().getUsername());
            List orderDetailList = entity.getOrderdetails();
            if(orderDetailList!=null && orderDetailList.size()>0){
                System.out.println("訂單明細:");
                for(int k=0;k<orderDetailList.size();k++){
                    OrderDetail od = (OrderDetail)orderDetailList.get(k);
                    System.out.println("商品id:"+od.getItemsId()+"----商品數量:"+od.getItemsNum());
                }
            }
            System.out.print("\n");
        }
    }
    
    sqlSession.close();  
}

運行結果:

一對多測試:
訂單關聯用戶信息:
訂單id:1----訂單號:1000010----創建時間:2015-06-04 13:22:35----用戶id:1----用戶名:王五
訂單明細:
商品id:1----商品數量:1
商品id:2----商品數量:3

訂單關聯用戶信息:
訂單id:2----訂單號:1000011----創建時間:2015-07-08 13:22:41----用戶id:1----用戶名:王五
訂單明細:
商品id:3----商品數量:4

訂單關聯用戶信息:
訂單id:3----訂單號:1000012----創建時間:2015-07-17 14:13:23----用戶id:2----用戶名:張三
訂單明細:
商品id:2----商品數量:3

3.6、小結 

mybatis使用resultMapcollection對關聯查詢的多條記錄映射到一個list集合屬性中。

四、多對多查詢

4.1、需求:查詢用戶以及用戶購買的商品信息

4.2、映射思路

將用戶信息映射到user中;

user類中添加訂單列表屬性List<Orders> orderslist,將用戶創建的訂單映射到orderslist;

Orders中添加訂單明細列表屬性List<OrderDetail>orderdetials,將訂單的明細映射到orderdetials;

OrderDetail中添加Items屬性,將訂單明細所對應的商品映射到Item。

4.3、在ordersCustomMapper.xml中添加如下代碼

1、定義resultMap

<!-- 查詢用戶即購買的商品信息的ResultMap -->
<resultMap type="com.mybatis.entity.User" id="userAndItemsResultMap">
    <!-- 用戶信息 -->
    <id column="user_id" property="id"/>
    <result column="username" property="username"/>
    <result column="sex" property="sex"/>
    <result column="address" property="address"/>
    
    <!-- 訂單信息, 一個用戶對應多個訂單,使用collection映射 -->
      <collection property="ordersList" ofType="com.mybatis.entity.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"/>
       
        <!-- 訂單明細,一個訂單包括 多個明細-->
        <collection property="orderdetails" ofType="com.mybatis.entity.OrderDetail">
            <id column="orderdetail_id" property="id"/>
            <result column="items_id"   property="itemsId"/>
            <result column="items_num"  property="itemsNum"/>
            <result column="orders_id"  property="ordersId"/>
            
            <!-- 商品信息,  一個訂單明細對應一個商品-->
            <association property="items" javaType="com.mybatis.entity.Items">
                <id column="items_id" property="id"/>
                <result column="items_name" property="itemsName"/>
                <result column="items_detail" property="detail"/>
                <result column="items_price" property="price"/>
            </association>
         </collection>
     </collection>     

</resultMap>

2、statement定義

<!-- 查詢用戶及用戶購買的商品信息,使用resultMap-->
<select id="findUserAndItemsResultMap" resultMap="userAndItemsResultMap">
    SELECT t1.*,t2.username,t2.sex,t2.address,t3.id orderdetail_id,t3.items_id,
    t3.items_num,t3.orders_id,t4.itemsname items_name,t4.detail items_detail,t4.price items_price
    FROM orders t1,t_user t2,orderdetail t3,items t4
    WHERE t1.user_id =  t2.id AND  t3.orders_id=t1.id AND t3.items_id = t4.id
</select>

4.4、在OrdersCustomMapper.java添加如下方法

/** 多對多:查詢用戶及用戶所購買的商品信息 */
public List<User> findUserAndItemsResultMap();

4.5、在Junit測試類中添加測試方法

/**
 * 多對多查詢
 * 查詢用戶及用戶購買的商品的信息
 */
@Test
public void TestFindUserAndItemsResultMap() {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    // 創建代理對象
    OrdersCustomMapper oc = sqlSession.getMapper(OrdersCustomMapper.class);
    // 調用mapper的方法
    List<User> list = oc.findUserAndItemsResultMap();
    if(list !=null && list.size()>0){
        System.out.println("多對多測試:");
        for(int i=0;i<list.size();i++){
            System.out.println("用戶信息:");
            User entity = (User)list.get(i);
            System.out.println("用戶id:"+entity.getId()+
                    "----用戶名:"+entity.getUsername());
            
            List ordersList = entity.getOrdersList();
            if(ordersList!=null && ordersList.size()>0){
                System.out.println("\n用戶購買的商品:");
                for(int k=0;k<ordersList.size();k++){
                    Orders o = (Orders)ordersList.get(k);
                    List orderDetailList = o.getOrderdetails();
                    
                    if(orderDetailList!=null && orderDetailList.size()>0){
                        for(int m=0;m<orderDetailList.size();m++){
                            OrderDetail d = (OrderDetail)orderDetailList.get(m);
                            Items item = d.getItems();
                            if(item != null){
                                System.out.println("商品id:"+item.getId()+
                                        "----商品名:"+item.getItemsName()+"----價格:"+item.getPrice()+
                                        "----商品描述:"+item.getDetail());
                            }
                        }
                    }
                }
                System.out.print("\n");
            }
        }
    }
    
    sqlSession.close();
}

測試結果:

多對多測試:
用戶信息:
用戶id:1----用戶名:王五

用戶購買的商品:
商品id:1----商品名:台式機----價格:3000.0----商品描述:該電腦質量非常好!
商品id:2----商品名:筆記本----價格:6000.0----商品描述:筆記本性能好,質量好!
商品id:3----商品名:背包----價格:200.0----商品描述:名牌背包,容量大質量好!

用戶信息:
用戶id:2----用戶名:張三

用戶購買的商品:
商品id:2----商品名:筆記本----價格:6000.0----商品描述:筆記本性能好,質量好!

五、resultType和resultMap總結

1、resultType:

  作用:將查詢結果按照sql列名pojo屬性名一致性映射到pojo中。

  場合:常見一些明細記錄的展示,比如用戶購買商品明細,將關聯查詢信息全部展示在頁面時,此時可直接使用resultType將每一條記錄映射到pojo中,在前端頁面遍歷list(list中是pojo)即可。

2、resultMap

  使用association和collection完成一對一和一對多高級映射(對結果有特殊的映射要求)。

(1)association:

作用:將關聯查詢信息映射到一個pojo對象中。

場合:為了方便查詢關聯信息可以使用association將關聯訂單信息映射為用戶對象的pojo屬性中,比如:查詢訂單及關聯用戶信息。使用resultType無法將查詢結果映射到pojo對象的pojo屬性中,根據對結果集查詢遍歷的需要選擇使用resultType還是resultMap。

(2)collection:

作用:將關聯查詢信息映射到一個list集合中。

場合:為了方便查詢遍歷關聯信息可以使用collection將關聯信息映射到list集合中,比如:查詢用戶權限范圍模塊及模塊下的菜單,可使用collection將模塊映射到模塊list中,將菜單列表映射到模塊對象的菜單list屬性中,這樣的作的目的也是方便對查詢結果集進行遍歷查詢。如果使用resultType無法將查詢結果映射到list集合中。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM