Mybatis 入門学習マッピング関連関係

目次

第 3 章 関連関係

第1節 コンセプト

1. アソシエーションの概念の説明

①数量関係

②関係の方向性

2. モデルを作成する

①エンティティクラスの作成

②データベーステーブルを作成し、テストデータを挿入する

第2クォーターの1対1

1. OrderMapperインターフェースを作成する

2. OrderMapper.xml 構成ファイルを作成します。

3. Mybatisグローバル設定ファイルにMapper設定ファイルを登録する

4. junitテストプログラム

5. キーワード

セクション 3 対多数

1. マッパーインターフェイスの作成

2. CustomerMapper.xml 構成ファイルを作成します。

3. リレーションシップと SQL ステートメントを構成する

4. junit テスト

5. キーワード

セクション 4 段階的な調査

1. 概念と要件

2、具体操作

①SQL文を書いて顧客に問い合わせる

②OrderをクエリするSQL文を書く

③SQL文を引用する

④各種要素間の対応関係

セクション 5 遅延ロード

1.コンセプト

2. 構成

①下位バージョン

②上位バージョン

3. junit テストを変更する

4. キーワードのまとめ

セクション 6 多対多のリレーションシップには中間テーブルが必要

1. 中間テーブルを使用しない場合

2. 中間テーブルを使用する

3. 中間テーブルに主キーを設定する

①オプション 1: 特別な主キー フィールドを設定する

②オプション 2: 共同主キーを使用する


第 3 章 関連関係

第1節 コンセプト

1. アソシエーションの概念の説明

①数量関係

主にデータベーステーブルに反映されます

  • 1対1

    配偶関係、本人およびID番号

  • 1対多の

    ユーザーとユーザーの注文、ロックとキー

  • 多対多

    教師と学生、学部と職員

②関係の方向性

主にJavaエンティティクラスに反映されます。

  • 双方向: 双方が相互にアクセスできます。
    • Customer: Order を含むコレクション属性
    • 注文: 単一の顧客の属性が含まれます
  • 一方向: 2 つの当事者のうちの 1 つだけが他の当事者にアクセスできます。
    • 顧客: コレクション属性に Order が含まれていないため、Order にアクセスできません。
    • 注文: 単一の顧客の属性が含まれます

2. モデルを作成する

①エンティティクラスの作成

public class Customer {
    
    private Integer customerId;
    private String customerName;
    private List<Order> orderList;// 体现的是对多的关系
public class Order {
    
    private Integer orderId;
    private String orderName;
    private Customer customer;// 体现的是对一的关系

②データベーステーブルを作成し、テストデータを挿入する

CREATE TABLE `t_customer` (
	 `customer_id` INT NOT NULL AUTO_INCREMENT, 
	 `customer_name` CHAR(100), 
	 PRIMARY KEY (`customer_id`) 
);
CREATE TABLE `t_order` ( 
	`order_id` INT NOT NULL AUTO_INCREMENT, 
	`order_name` CHAR(100), 
	`customer_id` INT, 
	PRIMARY KEY (`order_id`) 
); 
INSERT INTO `t_customer` (`customer_name`) VALUES ('c01');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o1', '1'); 
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o2', '1'); 
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o3', '1'); 

実際の開発では、通常、開発プロセス中にデータベース テーブルに外部キー制約は設定されません。

その理由は、デバッグの不便さを避けるためです。

通常、機能開発は完了し、バグがないかチェックするために外部キー制約を追加します。

 

第2クォーターの1対1

1. OrderMapperインターフェースを作成する

public interface OrderMapper {
    
    Order selectOrderWithCustomer(Integer orderId);
    
}

2. OrderMapper.xml 構成ファイルを作成します。

<!-- 创建resultMap实现“对一”关联关系映射 -->
<!-- id属性:通常设置为这个resultMap所服务的那条SQL语句的id加上“ResultMap” -->
<!-- type属性:要设置为这个resultMap所服务的那条SQL语句最终要返回的类型 -->
<resultMap id="selectOrderWithCustomerResultMap" type="com.atguigu.mybatis.entity.Order">

    <!-- 先设置Order自身属性和字段的对应关系 -->
    <id column="order_id" property="orderId"/>
    <result column="order_name" property="orderName"/>

    <!-- 使用association标签配置“对一”关联关系 -->
    <!-- property属性:在Order类中对一的一端进行引用时使用的属性名 -->
    <!-- javaType属性:一的一端类的全类名 -->
    <association property="customer" javaType="com.atguigu.mybatis.entity.Customer">
        <!-- 配置Customer类的属性和字段名之间的对应关系 -->
        <id column="customer_id" property="customerId"/>
        <result column="customer_name" property="customerName"/>
    </association>

</resultMap>

<!-- Order selectOrderWithCustomer(Integer orderId); -->
<select id="selectOrderWithCustomer" resultMap="selectOrderWithCustomerResultMap">
    SELECT order_id,order_name,c.customer_id,customer_name
    FROM t_order o
    LEFT JOIN t_customer c
    ON o.customer_id=c.customer_id
    WHERE o.order_id=#{orderId}
</select>

対応関係は下図をご参照ください。

3. Mybatisグローバル設定ファイルにMapper設定ファイルを登録する

<!-- 注册Mapper配置文件:告诉Mybatis我们的Mapper配置文件的位置 -->
<mappers>
    <!-- 在mapper标签的resource属性中指定Mapper配置文件以“类路径根目录”为基准的相对路径 -->
    <mapper resource="com/atguigu/mybatis/mapper/OrderMapper.xml"/>
</mappers>

4. junitテストプログラム

@Test
public void testRelationshipToOne() {
    OrderMapper orderMapper = session.getMapper(OrderMapper.class);
    
    // 查询Order对象,检查是否同时查询了关联的Customer对象
    Order order = orderMapper.selectOrderWithCustomer(2);
    System.out.println("order = " + order);
}

5. キーワード

「1 対 1」の関連付けには多くの設定がありますが、キーワードは関連付けと javaType だけです。

セクション 3 対多数

1. マッパーインターフェイスの作成

public interface CustomerMapper {
    
    Customer selectCustomerWithOrderList(Integer customerId);
    
}

2. CustomerMapper.xml 構成ファイルを作成します。

注: Mybatis グローバル構成ファイルに登録することを忘れないでください。

3. リレーションシップと SQL ステートメントを構成する

<!-- 配置resultMap实现从Customer到OrderList的“对多”关联关系 -->
<resultMap id="selectCustomerWithOrderListResultMap"
           type="com.atguigu.mybatis.entity.Customer">
    
    <!-- 映射Customer本身的属性 -->
    <id column="customer_id" property="customerId"/>
    <result column="customer_name" property="customerName"/>
    
    <!-- collection标签:映射“对多”的关联关系 -->
    <!-- property属性:在Customer类中,关联“多”的一端的属性名 -->
    <!-- ofType属性:集合属性中元素的类型 -->
    <collection property="orderList" ofType="com.atguigu.mybatis.entity.Order">
        <!-- 映射Order的属性 -->
        <id column="order_id" property="orderId"/>
        <result column="order_name" property="orderName"/>
    
    </collection>
    
</resultMap>
    
<!-- Customer selectCustomerWithOrderList(Integer customerId); -->
<select id="selectCustomerWithOrderList" resultMap="selectCustomerWithOrderListResultMap">
    SELECT c.customer_id,c.customer_name,o.order_id,o.order_name
    FROM t_customer c
    LEFT JOIN t_order o
    ON c.customer_id=o.customer_id
    WHERE c.customer_id=#{customerId}
</select>

対応関係は下図をご参照ください。

4. junit テスト

@Test
public void testRelationshipToMulti() {
    
    CustomerMapper customerMapper = session.getMapper(CustomerMapper.class);
    
    // 查询Customer对象同时将关联的Order集合查询出来
    Customer customer = customerMapper.selectCustomerWithOrderList(1);
    
    System.out.println("customer.getCustomerId() = " + customer.getCustomerId());
    System.out.println("customer.getCustomerName() = " + customer.getCustomerName());
    
    List<Order> orderList = customer.getOrderList();
    for (Order order : orderList) {
        System.out.println("order = " + order);
    }
    
}

5. キーワード

「対多」関係にも多くの構成がありますが、最も重要なものは「コレクション」と「ofType」です。

 

セクション 4 段階的な調査

1. 概念と要件

遅延読み込みを実現するには、実現する前に Customer と Order のクエリを 2 つのステップに分割して分割する必要があります。これを行うには、Order を個別にクエリする必要があります。つまり、Mapper 構成ファイル内の Order コレクション データをクエリするための別の SQL ステートメントを作成する必要があります。

2、具体操作

①SQL文を書いて顧客に問い合わせる

<!-- 专门指定一条SQL语句,用来查询Customer,而且是仅仅查询Customer本身,不携带Order -->
<select id="selectCustomerWithOrderList" resultMap="selectCustomerWithOrderListResultMap">
    select customer_id,customer_name from t_customer
    where customer_id=#{customerId}
</select>

②OrderをクエリするSQL文を書く

<select id="selectOrderList" resultType="com.atguigu.mybatis.entity.Order">
    select order_id,order_name from t_order where customer_id=#{customer_id}
</select>

③SQL文を引用する

<!-- orderList集合属性的映射关系,使用分步查询 -->
<!-- 在collection标签中使用select属性指定要引用的SQL语句 -->
<!-- select属性值的格式是:Mapper配置文件的名称空间.SQL语句id -->
<!-- column属性:指定Customer和Order之间建立关联关系时所依赖的字段 -->
<collection
    property="orderList"
    select="com.atguigu.mybatis.mapper.CustomerMapper.selectOrderList"
    column="customer_id"/>

Mapper インターフェースの抽象メソッドが変更されない場合、juni テストも変更されません。実行結果は以下の通りです。

DEBUG 11-30 11:10:05,796 ==>  Preparing: select customer_id,customer_name from t_customer where customer_id=?   (BaseJdbcLogger.java:145) 
DEBUG 11-30 11:10:05,866 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
DEBUG 11-30 11:10:05,889 ====>  Preparing: select order_id,order_name from t_order where customer_id=?   (BaseJdbcLogger.java:145) 
DEBUG 11-30 11:10:05,890 ====> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
DEBUG 11-30 11:10:05,895 <====      Total: 3  (BaseJdbcLogger.java:145) 
DEBUG 11-30 11:10:05,896 <==      Total: 1  (BaseJdbcLogger.java:145) 
customer = c01
order = Order{orderId=1, orderName='o1'}
order = Order{orderId=2, orderName='o2'}
order = Order{orderId=3, orderName='o3'}

④各種要素間の対応関係

セクション 5 遅延ロード

1.コンセプト

顧客にクエリを実行する場合、注文リストのコレクション データは使用できない場合があります。オーダーのコレクション データがまったく使用されない場合、データのこの部分が占有するメモリは無駄になります。この点において、必ずしも使用されるとは限らないデータが必要なときにクエリできることを望んでいます。

たとえば、Customer に対する 1,000 件のクエリのうち、Order コレクション データを使用するクエリは 15 件のみであるため、必要な場合にのみクエリを実行することで、メモリ スペースを大幅に節約できます。

遅延読み込みの概念: エンティティ クラスに関連付けられたプロパティは、必要になるまでクエリされません。遅延読み込みとも呼ばれます。

2. 構成

①下位バージョン

Mybatis グローバル構成ファイルで設定を構成する

<!-- 使用settings对Mybatis全局进行设置 -->
<settings>
    <!-- 开启延迟加载功能:需要配置两个配置项 -->
    <!-- 1、将lazyLoadingEnabled设置为true,开启懒加载功能 -->
    <setting name="lazyLoadingEnabled" value="true"/>

    <!-- 2、将aggressiveLazyLoading设置为false,关闭“积极的懒加载” -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

公式ドキュメントのaggressiveLazyLoading属性の説明:

有効にすると、遅延ロード プロパティを持つオブジェクトは、いずれかの遅延プロパティの呼び出し時に完全にロードされます。それ以外の場合、各プロパティはオンデマンドでロードされます。

②上位バージョン

<!-- Mybatis全局配置 -->
<settings>
    <!-- 开启延迟加载功能 -->
    <setting name="lazyLoadingEnabled" value="true"/>
</settings>

3. junit テストを変更する

@Test
public void testSelectCustomerWithOrderList() throws InterruptedException {
    
    CustomerMapper mapper = session.getMapper(CustomerMapper.class);
    
    Customer customer = mapper.selectCustomerWithOrderList(1);
    
    // 这里必须只打印“customerId或customerName”这样已经加载的属性才能看到延迟加载的效果
    // 这里如果打印Customer对象整体则看不到效果
    System.out.println("customer = " + customer.getCustomerName());
    
    // 先指定具体的时间单位,然后再让线程睡一会儿
    TimeUnit.SECONDS.sleep(5);
    
    List<Order> orderList = customer.getOrderList();
    
    for (Order order : orderList) {
        System.out.println("order = " + order);
    }
}

効果: 最初に Customer 自体をクエリし、OrderList が必要な場合にのみ SQL ステートメントを送信してクエリを実行します。

DEBUG 11-30 11:25:31,127 ==>  Preparing: select customer_id,customer_name from t_customer where customer_id=?   (BaseJdbcLogger.java:145) 
DEBUG 11-30 11:25:31,193 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
DEBUG 11-30 11:25:31,314 <==      Total: 1  (BaseJdbcLogger.java:145) 
customer = c01
DEBUG 11-30 11:25:36,316 ==>  Preparing: select order_id,order_name from t_order where customer_id=?   (BaseJdbcLogger.java:145) 
DEBUG 11-30 11:25:36,316 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
DEBUG 11-30 11:25:36,321 <==      Total: 3  (BaseJdbcLogger.java:145) 
order = Order{orderId=1, orderName='o1'}
order = Order{orderId=2, orderName='o2'}
order = Order{orderId=3, orderName='o3'}

4. キーワードのまとめ

「対多」関係における遅延読み込みの例を示しましたが、「対一」関係における構成方法は基本的に同じです。

接続関係 構成項目のキーワード 設定ファイル
1対1 関連タグ/javaType 属性 Mapper設定ファイルのresultMap
多くの人に コレクションタグ/ofType属性 Mapper設定ファイルのresultMap
一歩ずつ 関連タグ/属性の選択 Mapper設定ファイルのresultMap
1対多のステップ コレクションタグ/選択属性 Mapper設定ファイルのresultMap
遅延読み込み [低] LazyLoadingEnabled は true に設定され、
aggressiveLazyLoading は false に設定されます
Mybatis グローバル構成ファイルの設定
遅延読み込み [高] LazyLoadingEnabled は true に設定されます Mybatis グローバル構成ファイルの設定

 

 

セクション 6 多対多のリレーションシップには中間テーブルが必要

1. 中間テーブルを使用しない場合

特定のテーブルで、1 つのフィールドを使用して複数の「外部キー」値を格納すると、SQL ステートメントを使用して関連するクエリを実行できなくなります。

2. 中間テーブルを使用する

このようにして、SQL を使用して関連クエリを実行できます。ただ、関連付けには 3 つのテーブルが必要になる場合があります。

3. 中間テーブルに主キーを設定する

①オプション 1: 特別な主キー フィールドを設定する

②オプション 2: 共同主キーを使用する

結合主キーを使用する場合、複数のフィールドの組み合わせが繰り返されない限り、単一のフィールドを内部的に繰り返すことができます。

 

 

おすすめ

転載: blog.csdn.net/weixin_52733693/article/details/127508565