mybatis入門基礎(六)----高度なマッピング(一対一、一対多、多対多)

98264 ワード

mybatis入門基礎(六)----高度なマッピング(一対一、一対多、多対多)
時間2015-07-07 23:35:27
ブログ園エッセンスエリア
テキストhttp://www.cnblogs.com/selene/p/4627446.html
テーマ
MyBatis
一:注文商品データモデル
1.データベース実行スクリプト
データベース・テーブル・コードの作成:
 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
テストデータコード:
 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).各テーブルに記録されたデータ内容:モジュールを分けて各テーブルに記録された内容を熟知し、システムのニーズ(機能)を学ぶ過程に相当する.
(2).各テーブルの重要なフィールド設定:空でないフィールド、外部キーフィールド;
(3).データベース・レベル・テーブルとテーブルの関係:外部キー関係;
(4).表と表の間の業務関係:表と表の間の業務関係を分析する時、必ずある業務意義の基礎の上で分析しなければならない.
3.注文商品モデルに対するデータベース構想分析:
ユーザテーブル:t_user-->購入商品のユーザー情報が記録されています
注文表:orders-->ユーザーが作成した注文(商品を購入した注文)を記録します.
受注詳細:orderdetail-->受注の詳細、すなわち購入商品の情報を記録
商品表:items-->商品情報を記録している
テーブルとテーブルのビジネス関係:
テーブルとテーブルの間のビジネス関係を分析する際には、あるビジネス意義に基づいて分析する必要があります.
データ・レベル間の関係を持つテーブル間のビジネス関係を分析します.
t_userとorders:
t_user------>orders:1人のユーザーが複数の受注を作成でき、1対複数
orders--->t_user:受注は1人のユーザーのみで作成され、1対1です.
ordersとorderdetail:
orders----->orderdetail:1つの注文に複数の注文の詳細を含めることができます.1つの注文は複数の商品を購入することができ、各商品の購入情報はorderdetailで記録され、1対多の関係があるからです.
orderdetail-->orders:1つの注文の詳細は1つの注文にのみ含まれ、1対1です.
orderdetailとitesm:
orderdetail----->itesms:1つの注文明細は1つの商品情報にのみ対応し、1対1
items-->orderdetail:1つの商品は複数の注文明細、1対多に含めることができます
データベース・レベルに関係のないテーブル間にビジネス関係があるかどうかを再分析します.
ordersとitems:
ordersとitemsの間にはorderdetailテーブルを使用して関係を確立できます.
4.分析して対応する図を描くことで、業務関係を直感的に理解することができる
mybatis入门基础(六)----高级映射(一对一,一对多,多对多)_第1张图片
二、一対一のクエリ
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 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 orderdetails;
     //  getter and setter ......
}

商品実体: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 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の定義
 1 
 2     <resultMap type="com.mybatis.entity.Orders" id="OrdersUserResultMap">
 3         
 4         
 5         
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         
21         <association property="user" javaType="com.mybatis.entity.User">
22             
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     
 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 ListfindOrdersUserResultMap();

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 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 list = oc.findOrdersUserResultMap();
50         System.out.println(list);
51         sqlSession.close();
52 
53     }
54 
55 }
View Code
5.resultTypeとresultMapは一対一のクエリ・ノットを実現する
1対1のクエリーを実装するには、次の手順に従います.
a.resultType:resultTypeを使用すると簡単です.pojoにクエリーされたカラム名が含まれていない場合は、カラム名に対応する属性を追加する必要があります.
b.クエリ結果の特別な要求がない場合はresultTypeを使用することを推奨します.
c.resultMap:resultMapを個別に定義する必要があります.実装が面倒です.クエリーの結果に特別な要件がある場合は、resultMapを使用して、関連クエリーをpojoにマッピングするプロパティを完了します.
d.resultMapは遅延ロードを実現でき、resultTypeは遅延ロードを実現できない.
三、一対多クエリー
 3.1. 需要:注文(関連ユーザー)と注文明細を照会する.
 3.2.ordersでJAvaクラスにList orderDetailsプロパティ(上のエンティティが追加されています)を追加します.
最終的にはオーダー情報がordersにマッピングする、オーダーに対応するオーダー詳細がordersのorderDetails属性にマッピングされる.
3.3.オデッrsCustomMapperで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 type="com.mybatis.entity.Orders" id="ordersAndOrderDetailResultMap" extends="OrdersUserResultMap">
  
  
  
  
  <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"/>
  collection>
resultMap>

3.4. OrderCustomMapperでJAvaインタフェースクラスにメソッドを追加
/**    (    )      */
    public ListfindOrdersAndOrderDetailResultMap();

3.5.Junit試験クラスに試験方法を追加する
//     (    )         
  @Test
  public void TestFindOrdersAndOrderDetailResultMap() {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //       
    OrdersCustomMapper oc = sqlSession.getMapper(OrdersCustomMapper.class);
    //   mapper   
    List list = oc.findOrdersAndOrderDetailResultMap();
    System.out.println(list);
    sqlSession.close();  
  }

3.6. 小結
mybatisはresultMapのcollectionを使用して、関連クエリの複数のレコードをリストセット属性にマッピングします.
resultType実装を使用する:受注詳細をordersのorderdetailsにマッピングし、自分で処理する必要があります.二重ループループを使用して、重複レコードを削除し、受注詳細をorderdetailsに配置します.
四、多対多クエリー
4.1.需要:ユーザーおよびユーザーが購入した商品情報の照会
4.2.マッピングの考え方
ユーザー情報をuserにマッピングします.
userクラスに受注リスト属性List orderslistを追加し、ユーザーが作成した受注をorderslistにマッピングします.
Ordersに受注詳細リスト属性Listorderdetialsを追加し、受注の詳細をorderdetialsにマッピングします.
OrderDetailにItems属性を追加し、注文明細に対応する商品をItemにマッピングします.
4.3.OrdersCustomMapper.xmlは次のコードを追加します.

  <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 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>

<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 findUserAndItemsResultMap();

4.5.Junit試験クラスに試験方法を追加する
//                
  @Test
  public void TestFindUserAndItemsResultMap() {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //       
    OrdersCustomMapper oc = sqlSession.getMapper(OrdersCustomMapper.class);
    //   mapper   
    List list = oc.findUserAndItemsResultMap();
    System.out.println(list);
    sqlSession.close();
  }

4.6.resultMapまとめ
resultType :
役割:クエリー結果をsqlカラム名pojoプロパティ名の一貫性に従ってpojoにマッピングします.
場合:
ユーザーが商品の詳細を購入し、関連クエリー情報をすべてページに表示するなど、一般的な詳細レコードの展示では、resultTypeを使用して各レコードをpojoに直接マッピングし、フロントエンドページでlist(listではpojo)を巡回すればよい.
resultMap :
associationとcollectionを使用して、一対一と一対多の高度なマッピングを完了します(結果に特別なマッピング要件があります).
association :
役割:関連クエリー情報をpojoオブジェクトにマッピングします.
場合:
関連情報のクエリーを容易にするには、associationを使用して、関連受注情報をユーザー・オブジェクトのpojo属性にマッピングします.たとえば、受注のクエリーや関連ユーザー情報などです.
resultTypeを使用すると、pojoオブジェクトのpojoプロパティにクエリー結果をマッピングできません.結果セットのクエリー遍歴の必要に応じて、resultTypeとresultMapのどちらを使用するかを選択します.
collection :
≪アクション|Actions|emdw≫:関連クエリー情報をリスト・セットにマッピングします.
場合:
関連情報の検索を容易にするためにcollectionを使用して、ユーザー権限範囲モジュールおよびモジュールの下のメニューをクエリーするなどのリストセットに関連情報をマッピングします.collectionを使用してモジュールリストにモジュールをマッピングし、メニューリストをモジュールオブジェクトのメニューリスト属性にマッピングします.このような作業の目的も、クエリー結果セットの遍歴クエリーを容易にすることです.
resultTypeを使用してリストセットにクエリー結果をマッピングできない場合.