mybatis入門基礎(六)----高級映射(一對一,一對多,多對多)

一:訂單商品數據模型

1.數據庫執行腳本前端

  建立數據庫表代碼:java

 1 CREATE TABLE items (
 2   id INT NOT NULL  AUTO_INCREMENT,
 3   itemsname VARCHAR(32) NOT NULL COMMENT '商品名稱',
 4   price FLOAT(10,1) NOT NULL COMMENT '商品訂價',
 5   detail TEXT COMMENT '商品描述',
 6   pic VARCHAR(64) DEFAULT NULL COMMENT '商品圖片',
 7   createtime DATETIME NOT NULL COMMENT '生產日期',
 8   PRIMARY KEY (id)
 9 )  DEFAULT CHARSET=utf8;
10 
11 /*Table structure for table `orderdetail` */
12 
13 CREATE TABLE orderdetail (
14   id INT NOT NULL AUTO_INCREMENT,
15  orders_id INT NOT NULL COMMENT '訂單id',
16   items_id INT NOT NULL COMMENT '商品id',
17   items_num INT  DEFAULT NULL COMMENT '商品購買數量',
18   PRIMARY KEY (id),
19   KEY `FK_orderdetail_1` (`orders_id`),
20   KEY `FK_orderdetail_2` (`items_id`),
21   CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
22   CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
23 )  DEFAULT CHARSET=utf8;
24 
25 /*Table structure for table `orders` */
26 
27 CREATE TABLE orders (
28   id INT NOT NULL AUTO_INCREMENT,
29   user_id INT NOT NULL COMMENT '下單用戶id',
30   number VARCHAR(30) NOT NULL COMMENT '訂單號',
31   createtime DATETIME NOT NULL COMMENT '建立訂單時間',
32   note VARCHAR(100) DEFAULT NULL COMMENT '備註',
33   PRIMARY KEY (`id`),
34   KEY `FK_orders_1` (`user_id`),
35   CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
36 )  DEFAULT CHARSET=utf8;
37 
38 /*Table structure for table `t_user` */
39 
40 CREATE TABLE t_user (
41   id INT NOT NULL AUTO_INCREMENT,
42   username VARCHAR(32) NOT NULL COMMENT '用戶名稱',
43   birthday DATE DEFAULT NULL COMMENT '生日',
44   sex CHAR(1) DEFAULT NULL COMMENT '性別',
45   address  VARCHAR(256) DEFAULT NULL COMMENT '地址',
46   PRIMARY KEY (`id`)
47 ) DEFAULT CHARSET=utf8;
View Code

  測試數據代碼:sql

 1 /*Data for the table `items` */
 2 
 3 INSERT  INTO items(itemsname,price,detail,pic,createtime) VALUES 
 4 ('臺式機',3000.0,'該電腦質量很是好!',NULL,'2015-07-07 13:28:53'),
 5 ('筆記本',6000.0,'筆記本性能好,質量好!',NULL,'2015-07-08 13:22:57'),
 6 ('揹包',200.0,'名牌揹包,容量大質量好!',NULL,'2015-07-010 13:25:02');
 7 
 8 /*Data for the table `orderdetail` */
 9 
10 INSERT  INTO `orderdetail`(`orders_id`,`items_id`,`items_num`) VALUES
11  (1,1,1),
12  (1,2,3),
13  (2,3,4),
14  (3,2,3);
15 
16 /*Data for the table `orders` */
17 
18 INSERT  INTO `orders`(`user_id`,`number`,`createtime`,`note`) VALUES 
19 (1,'1000010','2015-06-04 13:22:35',NULL),
20 (1,'1000011','2015-07-08 13:22:41',NULL),
21 (2,'1000012','2015-07-17 14:13:23',NULL),
22 (3,'1000012','2015-07-16 18:13:23',NULL),
23 (4,'1000012','2015-07-15 19:13:23',NULL),
24 (5,'1000012','2015-07-14 17:13:23',NULL),
25 (6,'1000012','2015-07-13 16:13:23',NULL);
26 
27 /*Data for the table `user` */
28 
29 INSERT  INTO `t_user`(`username`,`birthday`,`sex`,`address`) VALUES 
30 ('王五',NULL,'2',NULL),
31 ('張三','2014-07-10','1','北京市'),
32 ('張小明',NULL,'1','河南鄭州'),
33 ('陳小明',NULL,'1','河南鄭州'),
34 ('張三丰',NULL,'1','河南鄭州'),
35 ('陳小明',NULL,'1','河南鄭州'),
36 ('王五',NULL,NULL,NULL),
37  ('小A','2015-06-27','2','北京'),
38 ('小B','2015-06-27','2','北京'),
39 ('小C','2015-06-27','1','北京'),
40 ('小D','2015-06-27','2','北京');
View Code

2.數據模型分析思路數據庫

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

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

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

(4).表與表之間的業務關係:在分析表與表之間的業務關係時必定要創建在某個業務意義基礎上去分析app

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

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

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

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

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

表與表之間的業務關係:

  在分析表與表之間的業務關係時須要創建 在某個業務意義基礎上去分析。

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

t_userorders

  t_user---->orders:一個用戶能夠建立多個訂單,一對多

  orders--->t_user:一個訂單隻由一個用戶建立,一對一

orders和orderdetail

  orders--->orderdetail:一個訂單能夠包括多個訂單明細,由於一個訂單能夠購買多個商品,每一個商品的購買信息在orderdetail記錄,一對多關係

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

orderdetail和itesm

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

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

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

orders和items

  ordersitems之間能夠經過orderdetail表創建 關係。

4.分析以後畫出對應的圖,方便直觀的瞭解業務關係

2、一對一查詢

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

2.2.resultType實現

2.2.1.sql語句   

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

1 SELECT    t1.*,
2         t2.username,
3         t2.sex,
4         t2.address
5     FROM 
6         orders t1,
7         t_user t2
8 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 阿赫瓦里
 */
public class User {
    private Integer id;
    // 姓名
    private String username;
    // 性別
    private String sex;
    // 地址
    private String address;
    // 生日
    private Date birthday;
    // 用戶建立的訂單列表
    private List<Orders> ordersList;
       // getter and setter ......
}

訂單實體:orders.java

package com.mybatis.entity;
import java.util.Date;
import java.util.List;
/**
 * @ClassName: Orders
 * @Description: TODO(訂單實體)
 * @author 阿赫瓦里
 */
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;
       //  getter and setter ......
}

商品實體:Items.java

package com.mybatis.entity;
import java.util.Date;
/**
 * @ClassName: Items
 * @Description: TODO(商品實體類)
 * @author 阿赫瓦里
 */
public class Items {
    /** 商品表主鍵Id */
    private Integer id;
    /** 商品名稱 */
    private String itemsName;
    /** 商品訂價 */
    private float price;
    /** 商品描述 */
    private String detail;
    /** 商品圖片 */
    private String picture;
    /** 生產日期 */
    private Date createTime;
// getter and setter ......
}

訂單明細實體:OrderDetail.java

package com.mybatis.entity;
/**
 * @ClassName: OrderDetail
 * @Description: TODO(訂單明細實體)
 * @author 阿赫瓦里
 */
public class OrderDetail {
    /** 主鍵,訂單明細表Id */
    private Integer id;
    /** 訂單Id */
    private Integer ordersId;
    /** 商品id */
    private Integer itemsId;
    /** 商品購買數量 */
    private Integer itemsNum;
    // 明細對應的商品信息
    private Items items;
        //  getter and setter ......
}

 建立一個包裝類,將查詢到的信息能夠所有映射到此類: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;

/**
 * @ClassName: OrdersMapperCustom
 * @Description: TODO(OrdersMapperCustom的mapper)
 * @author 阿赫瓦里
 */
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">
<!-- namespace命名空間,做用就是對sql進行分類化的管理,理解爲sql隔離
    注意:使用mapper代理開發時,namespace有特殊做用,namespace等於mapper接口地址
 -->
<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

 1 <!-- 定義查詢訂單關聯用戶的 resultMap,將整個的查詢結果映射到com.mybatis.entity.Orders中 -->
 2     <resultMap type="com.mybatis.entity.Orders" id="OrdersUserResultMap">
 3         <!-- 配置映射的訂單信息 -->
 4         
 5         <!-- id:查詢列中的惟一標識,訂單信息中的惟一標識,若是多列組成惟一標識(如:通常數據庫設計中的字典表 使用聯合主鍵),就須要配置多個id 
 6             column:訂單信息的惟一標識 列
 7             property:訂單信息的惟一標識列所映射到orders中的那個屬性(假如:數據庫中orders表中的主鍵爲orders_id,而實體屬性名稱爲ordersId,
 8                 則這個配置應爲<id column="orders_id" property="ordersId"/>,相似hibernate實體映射文件配置)。
 9         -->
10         <id column="id" property="id"/>
11         <result column="user_id" property="userid"/>
12         <result column="number" property="number"/>
13         <result column="createtime" property="createTime"/>
14         <result column="note" property="note"/>
15         
16         <!-- 配置映射的關聯用戶信息 -->
17         
18         <!--association:用於映射關聯查詢單個對象的信息
19             property:要將關聯查詢的用戶信息映射到Orders中那個屬性
20           -->
21         <association property="user" javaType="com.mybatis.entity.User">
22             <!-- id:關聯查詢用戶的惟一標識 
23                 column:指定惟一標識用戶信息的列
24                 property:映射到user的那個屬性
25             -->
26             <id column="user_id" property="id"/>
27             <result column="username" property="username"/>
28             <result column="sex" property="sex"/>
29             <result column="address" property="address"/>
30         </association>
31         
32     </resultMap>

   2. statement定義

 1     <!-- 查詢訂單,關聯查詢用戶信息,使用resultMap實現 -->
 2     <select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap">
 3             SELECT t1.*,
 4                 t2.username,
 5                 t2.sex,
 6                 t2.address
 7             FROM
 8                 orders t1,
 9                 t_user t2
10             WHERE t1.user_id=t2.id
11     </select>

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

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

4.對是resultType和resultMap實現的Junit測試

 1 package com.mybatis.test;
 2 
 3 import java.io.InputStream;
 4 import java.util.List;
 5 
 6 import org.apache.ibatis.io.Resources;
 7 import org.apache.ibatis.session.SqlSession;
 8 import org.apache.ibatis.session.SqlSessionFactory;
 9 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
10 import org.junit.Before;
11 import org.junit.Test;
12 
13 import com.mybatis.entity.Orders;
14 import com.mybatis.entity.OrdersCustom;
15 import com.mybatis.mapper.OrdersCustomMapper;
16 
17 public class OrdersCustomMapperTest {
18 
19     private SqlSessionFactory sqlSessionFactory;
20 
21     // 此方法是在執行findUserByIdTest以前執行
22     @Before
23     public void setUp() throws Exception {
24         String resource = "SqlMapConfig.xml";
25         InputStream inputStream = Resources.getResourceAsStream(resource);
26         // 建立SqlSessionFcatory
27         sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
28     }
29 
30     // 查詢訂單,關聯查詢用戶信息,使用resultType實現的測試
31     @Test
32     public void TestFindOrdersUser() {
33         SqlSession sqlSession = sqlSessionFactory.openSession();
34         // 建立代理對象
35         OrdersCustomMapper oc = sqlSession.getMapper(OrdersCustomMapper.class);
36         // 調用mapper的方法
37         List<OrdersCustom> list = oc.findOrdersUser();
38         System.out.println(list);
39         sqlSession.close();
40     }
41 
42     // 查詢訂單,關聯查詢用戶信息,使用resultMap實現的測試
43     @Test
44     public void TestFindOrdersUserResultMap() {
45         SqlSession sqlSession = sqlSessionFactory.openSession();
46         // 建立代理對象
47         OrdersCustomMapper oc = sqlSession.getMapper(OrdersCustomMapper.class);
48         // 調用mapper的方法
49         List<Orders> list = oc.findOrdersUserResultMap();
50         System.out.println(list);
51         sqlSession.close();
52 
53     }
54 
55 }
View Code

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

 實現一對一查詢:

  a.resultType:使用resultType實現較爲簡單,若是pojo中沒有包括查詢出來的列名,須要增長列名對應的屬性,便可完成映射。

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

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

  d.resultMap能夠實現延遲加載,resultType沒法實現延遲加載。

3、一對多查詢

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

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

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

3.3.在ordersCustomMapper.xml中添加以下代碼

    <!-- 查詢訂單關聯查詢用戶及訂單明細 -->
    <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>

resultMap的定義一樣添加到ordersCustomMapper.xml

<!-- 查詢訂單(關聯用戶)及訂單明細的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>

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

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

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

// 查詢訂單(關聯用戶)以及訂單明細的測試
    @Test
    public void TestFindOrdersAndOrderDetailResultMap() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 建立代理對象
        OrdersCustomMapper oc = sqlSession.getMapper(OrdersCustomMapper.class);
        // 調用mapper的方法
        List<OrderDetail> list = oc.findOrdersAndOrderDetailResultMap();
        System.out.println(list);
        sqlSession.close();  
    }

3.6. 小結 

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

 使用resultType實現:將訂單明細映射到orders中的orderdetails中,須要本身處理,使用雙重循環遍歷,去掉重複記錄,將訂單明細放在orderdetails中。

4、多對多查詢

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

4.2.映射思路

  將用戶信息映射到user中。

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

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

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

4.3.OrdersCustomMapper.xml添加以下代碼

<!-- 查詢用戶即購買的商品信息的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>
    <!-- 查詢用戶及用戶購買的商品信息,使用resulaMap-->
    <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. 在OrderCustomMapper.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();
        System.out.println(list);
        sqlSession.close();
    }

4.6.resultMap總結

resultType

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

  場合

    常見一些明細記錄的展現,好比用戶購買商品明細,將關聯查詢信息所有展現在頁面時,此時可直接使用resultType將每一條記錄映射到pojo中,在前端頁面遍歷listlist中是pojo)便可。

resultMap

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

association

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

  場合

    爲了方便查詢關聯信息可使用association將關聯訂單信息映射爲用戶對象的pojo屬性中,好比:查詢訂單及關聯用戶信息。

    使用resultType沒法將查詢結果映射到pojo對象的pojo屬性中,根據對結果集查詢遍歷的須要選擇使用resultType仍是resultMap

collection

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

  場合

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

  若是使用resultType沒法將查詢結果映射到list集合中。

相關文章
相關標籤/搜索