Mybatis introductory learning mapping association relationship

Table of contents

Chapter 3 Related Relationships

Section 1 Concept

1. Explanation of the concept of association

①Quantity relationship

②The direction of the relationship

2. Create a model

①Create entity class

②Create a database table and insert test data

One on one in the second quarter

1. Create the OrderMapper interface

2. Create the OrderMapper.xml configuration file

3. Register the Mapper configuration file in the Mybatis global configuration file

4. junit test program

5. Keywords

Section 3 versus many

1. Create Mapper interface

2. Create the CustomerMapper.xml configuration file

3. Configure relationships and SQL statements

4. junit test

5. Keywords

Section 4 Step-by-Step Inquiry

1. Concepts and requirements

2.Specific operations

①Write SQL statements to query Customer

②Write the SQL statement to query Order

③Quote SQL statements

④Correspondence between various elements

Section 5 Lazy Loading

1. Concept

2. Configuration

①Lower version

②Higher version

3. Modify junit test

4. Keyword summary

Section 6 Many-to-many relationships require intermediate tables

1. If you do not use intermediate tables

2. Use intermediate tables

3. Set the primary key in the intermediate table

①Option 1: Set up a special primary key field

②Option 2: Use joint primary key


Chapter 3 Related Relationships

Section 1 Concept

1. Explanation of the concept of association

①Quantity relationship

Mainly reflected in database tables

  • One to one

    Spousal relationship, person and ID number

  • one to many

    User and user orders, locks and keys

  • many to many

    Teachers and students, departments and staff

②The direction of the relationship

Mainly reflected in Java entity classes

  • Bidirectional: Both parties can access each other
    • Customer: Collection attribute containing Order
    • Order: Contains attributes of a single Customer
  • One-way: Only one of the two parties can access the other party
    • Customer: The collection attribute does not contain Order, and Order cannot be accessed.
    • Order: Contains attributes of a single Customer

2. Create a model

①Create entity class

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 a database table and insert test data

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'); 

In actual development, foreign key constraints are generally not set for database tables during the development process.

The reason is to avoid debugging inconvenience.

Generally, the function development is completed, and foreign key constraints are added to check whether there are bugs.

 

One on one in the second quarter

1. Create the OrderMapper interface

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

2. Create the OrderMapper.xml configuration file

<!-- 创建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>

For the corresponding relationship, please refer to the figure below:

3. Register the Mapper configuration file in the Mybatis global configuration file

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

4. junit test program

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

5. Keywords

In the "one-to-one" association, we have many configurations, but the only keywords are: association and javaType

Section 3 versus many

1. Create Mapper interface

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

2. Create the CustomerMapper.xml configuration file

Note: Don’t forget to register in the Mybatis global configuration file

3. Configure relationships and SQL statements

<!-- 配置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>

For the corresponding relationship, please refer to the figure below:

4. junit test

@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. Keywords

In the "to-many" relationship, there are also many configurations, but the most critical ones are: "collection" and "ofType"

 

Section 4 Step-by-Step Inquiry

1. Concepts and requirements

In order to achieve lazy loading, the query for Customer and Order must be separated and divided into two steps before it can be realized. To do this, we need to query the Order separately, that is, we need to write a separate SQL statement to query the Order collection data in the Mapper configuration file.

2.Specific operations

①Write SQL statements to query Customer

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

②Write the SQL statement to query Order

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

③Quote SQL statements

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

If the abstract methods in the Mapper interface do not change, then the juni test does not change either. The execution results are as follows:

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

④Correspondence between various elements

Section 5 Lazy Loading

1. Concept

When querying Customer, the Order's List collection data may not be used. If the Order's collection data is never used, the memory occupied by this part of the data is wasted. In this regard, we hope that data that may not necessarily be used can be queried when needed.

For example: among 1,000 queries for Customer, only 15 of them will use the Order collection data. Then querying only when needed can greatly save memory space.

The concept of lazy loading: The properties associated with the entity class are not queried until they are needed. Also called lazy loading.

2. Configuration

①Lower version

Configure settings in the Mybatis global configuration file

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

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

Explanation of the aggressiveLazyLoading attribute in the official documentation:

When enabled, an object with lazy loaded properties will be loaded entirely upon a call to any of the lazy properties.Otherwise, each property is loaded on demand.

②Higher version

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

3. Modify junit test

@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);
    }
}

Effect: First query the Customer itself at the beginning, and only send SQL statements to query when the OrderList is needed.

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. Keyword summary

We gave an example of lazy loading in a "to-many" relationship, and the configuration method in a "to-one" relationship is basically the same.

connection relation Configuration item keywords configuration file
One to one association tag/javaType attribute resultMap in Mapper configuration file
to many collection tag/ofType attribute resultMap in Mapper configuration file
step by step association tag/select attribute resultMap in Mapper configuration file
one-to-many step collection tag/select attribute resultMap in Mapper configuration file
Lazy loading [low] lazyLoadingEnabled is set to true
aggressiveLazyLoading is set to false
settings in the Mybatis global configuration file
Lazy loading [high] lazyLoadingEnabled is set to true settings in the Mybatis global configuration file

 

 

Section 6 Many-to-many relationships require intermediate tables

1. If you do not use intermediate tables

In a certain table, using one field to store multiple "foreign key" values ​​will make it impossible to use SQL statements to perform related queries.

2. Use intermediate tables

In this way, you can use SQL to perform related queries. It's just that three tables may be needed to correlate.

3. Set the primary key in the intermediate table

①Option 1: Set up a special primary key field

②Option 2: Use joint primary key

When using a joint primary key, as long as the combination of multiple fields is not repeated, a single field can be repeated internally.

 

 

Guess you like

Origin blog.csdn.net/weixin_52733693/article/details/127508565