MyBatis联合查询

文章目录

  • 数据库设计
  • [MyBatis 配置](#MyBatis 配置)
  • [MyBatis 映射文件](#MyBatis 映射文件)
    • [Mapper 接口](#Mapper 接口)
  • 总结

数据库设计

建表 SQL

sql 复制代码
CREATE TABLE user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL
);

CREATE TABLE `order` (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT NOT NULL,
    order_no VARCHAR(50) NOT NULL,
    FOREIGN KEY (user_id) REFERENCES user(id)
);

CREATE TABLE role (
    id INT PRIMARY KEY AUTO_INCREMENT,
    role_name VARCHAR(50) NOT NULL
);

CREATE TABLE user_role (
    user_id INT NOT NULL,
    role_id INT NOT NULL,
    PRIMARY KEY (user_id, role_id),
    FOREIGN KEY (user_id) REFERENCES user(id),
    FOREIGN KEY (role_id) REFERENCES role(id)
);

插入以下数据:

sql 复制代码
INSERT INTO user (name) VALUES ('Alice'), ('Bob');
INSERT INTO `order` (user_id, order_no) VALUES (1, 'ORD001'), (1, 'ORD002'), (2, 'ORD003');
INSERT INTO role (role_name) VALUES ('Admin'), ('User');
INSERT INTO user_role (user_id, role_id) VALUES (1, 1), (1, 2), (2, 2);

MyBatis 配置

我们使用 MySQL 数据库,MyBatis 的核心配置文件如下:

sql 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test_db?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

定义 Java 实体类,映射数据库表:

java 复制代码
@Data
public class User {
    private Integer id;
    private String name;
    private Order order; // 一对一:用户关联一个订单
    private List<Order> orders; // 一对多:用户关联多个订单
    private List<Role> roles; // 多对多:用户关联多个角色
}

@Data
public class Order {
    private Integer id;
    private Integer userId;
    private String orderNo;
}

@Data
public class Role {
    private Integer id;
    private String roleName;
}

MyBatis 映射文件

在 UserMapper.xml 中定义关联查询,展示一对一、一对多和多对多的实现。

xml 复制代码
<?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.example.mapper.UserMapper">

    <!-- 一对一 -->
    <resultMap id="UserWithOrderMap" type="com.example.entity.User">
        <id property="id" column="user_id"/>
        <result property="name" column="user_name"/>
        <association property="order" javaType="com.example.entity.Order">
            <id property="id" column="order_id"/>
            <result property="userId" column="user_id"/>
            <result property="orderNo" column="order_no"/>
        </association>
    </resultMap>
   
    <select id="selectUserWithOrder" resultMap="UserWithOrderMap">
        SELECT *
        FROM user u
        LEFT JOIN `order` o ON u.id = o.user_id
        WHERE u.id = #{id}
        LIMIT 1
    </select>

    <!-- 一对多 -->
    <resultMap id="UserWithOrdersMap" type="com.example.entity.User">
        <id property="id" column="user_id"/>
        <result property="name" column="user_name"/>
        <collection property="orders" ofType="com.example.entity.Order">
            <id property="id" column="order_id"/>
            <result property="userId" column="user_id"/>
            <result property="orderNo" column="order_no"/>
        </collection>
    </resultMap>

    <select id="selectUserWithOrders" resultMap="UserWithOrdersMap">
        SELECT *
        FROM user u
        LEFT JOIN `order` o ON u.id = o.user_id
        WHERE u.id = #{id}
    </select>

    <!-- 多对多 -->
    <resultMap id="UserWithRolesMap" type="com.example.entity.User">
        <id property="id" column="user_id"/>
        <result property="name" column="user_name"/>
        <collection property="roles" ofType="com.example.entity.Role">
            <id property="id" column="role_id"/>
            <result property="roleName" column="role_name"/>
        </collection>
    </resultMap>
    
    <select id="selectUserWithRoles" resultMap="UserWithRolesMap">
        SELECT *
        FROM user u
        LEFT JOIN user_role ur ON u.id = ur.user_id
        LEFT JOIN role r ON ur.role_id = r.id
        WHERE u.id = #{id}
    </select>
</mapper>

Mapper 接口

定义对应的 Mapper 接口:

java 复制代码
public interface UserMapper {
    User selectUserWithOrder(Integer id); // 一对一
    User selectUserWithOrders(Integer id); // 一对多
    User selectUserWithRoles(Integer id); // 多对多
}

以下是测试代码,验证查询结果:

java 复制代码
public class MyBatisTest {
    public static void main(String[] args) throws Exception {
        SqlSessionFactory factory = new SqlSessionFactoryBuilder()
                .build(new FileInputStream("mybatis-config.xml"));
        try (SqlSession session = factory.openSession()) {
            UserMapper mapper = session.getMapper(UserMapper.class);

            // 测试一对一
            User userWithOrder = mapper.selectUserWithOrder(1);
            System.out.println(userWithOrder.getName());

            // 测试一对多
            User userWithOrders = mapper.selectUserWithOrders(1);
            System.out.println(userWithOrders.getName());
            userWithOrders.getOrders().forEach(order -> System.out.println("  - " + order.getOrderNo()));

            // 测试多对多
            User userWithRoles = mapper.selectUserWithRoles(1);
            System.out.println(userWithRoles.getName());
            userWithRoles.getRoles().forEach(role -> System.out.println("  - " + role.getRoleName()));
        }
    }
}

总结

一对一:通过 association 标签,查询用户及其关联的一个订单。

一对多:通过 collection 标签,查询用户及其所有订单,MyBatis 自动将多行订单数据映射到 List。

多对多:通过 collection 标签,查询用户及其所有角色,借助中间表 user_role 实现关联。

相关推荐
Mr Aokey2 小时前
从BaseMapper到LambdaWrapper:MyBatis-Plus的封神之路
java·eclipse·mybatis
真实的菜5 小时前
MyBatis核心配置深度解析:从XML到映射的完整技术指南
xml·tomcat·mybatis
Asu520216 小时前
思途AOP学习笔记 0806
java·sql·学习·mybatis
期待のcode19 小时前
配置Mybatis环境
java·tomcat·mybatis
熊猫片沃子1 天前
mybatis 与mybatisplus 比较总结
java·后端·mybatis
寒士obj1 天前
MyBatis基础操作完整指南
mybatis
Asu52022 天前
思途Mybatis学习 0805
java·spring boot·学习·mybatis
Mr Aokey2 天前
注解退散!纯XML打造MyBatis持久层的终极形态
xml·java·mybatis
Noii.2 天前
Mybatis的应用及部分特性
java·数据库·mybatis