mybatis - 多表映射(对一映射、对多映射)

文章目录


实体类设计

对一关系

  • 对一关系:
    类中只要包含 单个对方对象类型 属性,即可
    如:夫妻一方对应另一方,一个订单对应一个用户,都是对一关系
java 复制代码
public class Customer {
  private Integer customerId;
  private String customerName;
}

public class Order {
  private Integer orderId;
  private String orderName;
  private Customer customer; "对一关系(一个订单,对应,一个客户)"
}

对多关系

  • 对多关系:
    类中只要包含 对方类型的集合 属性,即可
java 复制代码
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; "对一关系(一个订单,对应,一个客户)"
}

多表结果实体类,设计小技巧

  • 对一,属性中包含 对方对象

  • 对多,属性中包含 对方对象的集合

  • 无论多少张表联查,实体类设计都是两两考虑!

  • 只有真实发生多表查询时,才需要设计和修改实体类,否则,不提前设计和修改实体类!

  • 在查询映射的时候,只需要关注本次查询相关的属性!

    如:查询订单和对应的客户,就不要关注客户中的订单集合!



例子

Order 实体类 及其mapper接口

java 复制代码
"Order - 实体类"
package com.english.pojo;
import lombok.Data;
@Data
public class Order {
    private Integer orderId;
    private String orderName;
    private Customer customer; // 对一关系(一个订单,只能对应,一个客户)
}


"Order - mapper接口"
package com.english.mapper;
import com.english.pojo.Order;
public interface OrderMapper {
    // 根据ID,查询订单,以及订单关联的用户的信息
    Order selectOrderWithCustomer(Integer orderId);
}

Customer 实体类 及其mapper接口

java 复制代码
"Customer - 实体类"
package com.english.pojo;
import lombok.Data;
import java.util.List;
@Data
public class Customer {
    private Integer customerId;
    private String customerName;
    private List<Order> orderList; // 对多关系(一个客户,有,多个订单)
}


"Customer- mapper接口"
package com.english.mapper;
import com.english.pojo.Customer;
public interface CustomerMapper {
    // 查询客户,以及客户关联的订单信息
    Customer selectCustomerWithOrderList(Integer customerId);
}

OrderMapper.xml 映射文件

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 声明XML文档类型为mapper,它告诉解析器该文档应该符合 MyBatis 的 mapper DTD -->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTO Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- mapper:namespace:指定,与之关联的Java接口的权限定符-->
<mapper namespace="com.english.mapper.OrderMapper">
    <!-- 创建resultMap实现"对一"关联关系映射 -->
    <!-- id:  设置为这个resultMap所服务的那条SQL语句的id加上"ResultMap" -->
    <!-- type:设置为这个resultMap所服务的那条SQL语句最终要返回的类型 -->
    <resultMap id="selectOrderWithCustomerResultMap" type="order">
        <id column="order_id" property="orderId"/>
        <result column="order_name" property="orderName"/>

        <!-- association标签:配置"对一"关联关系 -->
        <!-- property:Order类中的 private Customer customer 这个属性 -->
        <!-- javaType:property="customer"是什么类型数据 -->
        <association property="customer" javaType="com.english.pojo.Customer">
        <!-- <association property="customer" javaType="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>
</mapper>

CustomerMapper.xml 映射文件

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTO Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
        
<mapper namespace="com.english.mapper.CustomerMapper">
    <resultMap id="selectCustomerWithOrderListResultMap" type="customer">
        <id column="customer_id" property="customerId"/>
        <result column="customer_name" property="customerName"/>

        <!-- collection:映射 "对多" 的关联关系 -->
        <!-- property:Customer类中的 private List<Order> orderList 这个属性 -->
        <!-- ofType:集合中元素的类型 -->
        <collection property="orderList" ofType="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>
</mapper>

mybatis-config.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTO Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <settings>
        <!-- 开启mybatis的日志输出,使用system进行控制台输出 -->
        <setting name="logImpl" value="STDOUT_LOGGING"/>

        <!-- 开启,驼峰式自动映射(数据库表中某列是a_col,映射到java中就成了aCol) -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <typeAliases>
        <!-- 方式1:单独定义-->
        <!-- <typeAlias type="com.atguigu.pojo.Employee" alias="ergouzi"/> -->

        <!-- 方式2:批量将包下的类,给与别名,别名就是类的首字母小写 -->
        <package name="com.english.pojo" />
        <!-- 在方式2的情况下,如果某个文件需要单独设置别名,将注解@Alias("ergouzi")加到这个类上即可 -->
    </typeAliases>

    <!-- 配置mybatis的开发环境,使用 default 指定实际运行时使用的环境 -->
    <environments default="development">
        <environment id="development">
            <!-- transactionManager:配置 Mybatis 的 内置事务管理器,type设置为JDBC,表示,使用MyBatis内置的JDBC事务管理器 -->
            <transactionManager type="JDBC"></transactionManager>

            <!-- dataSource:配置数据源,type属性设置为POOLED,表示使用连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///my_study_db"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!-- mappers:用于配置Mapper映射文件,这里注册了一个位于mappers目录下的EmployeeMapper.xml文件。-->
    <mappers>
        <mapper resource="mappers/OrderMapper.xml"/>
        <mapper resource="mappers/CustomerMapper.xml"/>
    </mappers>
</configuration>

测试文件

java 复制代码
import com.english.mapper.CustomerMapper;
import com.english.mapper.OrderMapper;
import com.english.pojo.Customer;
import com.english.pojo.Order;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

@Slf4j
public class MyTest {
    private SqlSession  sqlSession;

    // junit 会在每一个 @Test方法 前,执行 @BeforeEach方法
    @BeforeEach
    public void init() throws IOException {
        InputStream ipt = Resources.getResourceAsStream("mybatis-config.xml");
        sqlSession = new SqlSessionFactoryBuilder().build(ipt).openSession();
    }

    @Test
    public void test1(){
        OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
        Order order = orderMapper.selectOrderWithCustomer(2);
        log.info("order=" + order);
    }

    @Test
    public void test2(){
        CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
        Customer customer = customerMapper.selectCustomerWithOrderList(1);
        log.info("customer - id=" + customer.getCustomerId());
        log.info("customer - name=" + customer.getCustomerName());

        List<Order> orderList = customer.getOrderList();
        for (Order order : orderList) {
            log.info("order - =" + order);
        }
    }

    // junit 会在每一个 @Test方法 后,执行 @AfterEach方法
    @AfterEach
    public void clear(){
        sqlSession.commit();
        sqlSession.close();
    }
}

需要的依赖 pom.xml

xml 复制代码
<dependencies>
	<!-- mybatis依赖 -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
    </dependency>

    <!-- 数据库驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!--junit5测试-->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <!-- SLF4J API(日志门面) -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
    </dependency>

    <!-- 具体日志实现(如 Logback) -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
    </dependency>
</dependencies>
相关推荐
Albert Edison2 小时前
【ProtoBuf】初识 protobuf
java·开发语言·protobuf
码出财富10 小时前
SpringBoot 内置的 20 个高效工具类
java·spring boot·spring cloud·java-ee
我是小疯子6610 小时前
Python变量赋值陷阱:浅拷贝VS深拷贝
java·服务器·数据库
森叶10 小时前
Java 比 Python 高性能的原因:重点在高并发方面
java·开发语言·python
二哈喇子!10 小时前
Eclipse中导入外部jar包
java·eclipse·jar
微露清风10 小时前
系统性学习C++-第二十二讲-C++11
java·c++·学习
进阶小白猿11 小时前
Java技术八股学习Day20
java·开发语言·学习
gis开发11 小时前
【无标题】
java·前端·javascript
Wpa.wk11 小时前
性能测试 - 搭建线上的性能测试环境参考逻辑图
java·经验分享·测试工具·jmeter·性能测试