当前位置: 首页 > news >正文

MyBatis一对多查询方式

在 MyBatis 中,一对多查询是指一个实体对象(如 Order)关联多个子对象(如 OrderItem)。这种关系在数据库中通常通过外键实现,而在 MyBatis 中可以通过 resultMap 的嵌套集合(<collection>)来处理。

以下是对 MyBatis 中一对多查询的详细介绍,包括实现步骤和示例代码。


1. 一对多关系的数据表设计

假设我们有两个表:

  • Orders:存储订单信息。
  • OrderItems:存储订单项信息,每个订单项属于一个订单。

表结构如下:

CREATE TABLE Orders (
    order_id INT PRIMARY KEY,
    order_number VARCHAR(50),
    customer_id INT,
    order_date DATE
);

CREATE TABLE OrderItems (
    item_id INT PRIMARY KEY,
    order_id INT,
    product_name VARCHAR(100),
    quantity INT,
    price DECIMAL(10, 2),
    FOREIGN KEY (order_id) REFERENCES Orders(order_id)
);
  • 一个订单(Orders)可以包含多个订单项(OrderItems)。
  • OrderItems 表中的 order_id 是外键,指向 Orders 表的 order_id

2. 实体类设计

在 Java 中,我们需要定义两个实体类来表示这种一对多关系。

Order

public class Order {
    private int orderId;
    private String orderNumber;
    private int customerId;
    private Date orderDate;
    private List<OrderItem> orderItems; // 一对多关系

    // Getters and Setters
}

OrderItem

public class OrderItem {
    private int itemId;
    private int orderId;
    private String productName;
    private int quantity;
    private BigDecimal price;

    // Getters and Setters
}

3. MyBatis 实现一对多查询

在 MyBatis 中,一对多查询通常通过 resultMap<collection> 标签来实现。以下是具体步骤。

3.1 定义 resultMap

在 MyBatis 的 Mapper XML 文件中,定义一个 resultMap,使用 <collection> 标签来表示一对多关系。

<resultMap id="OrderResultMap" type="Order">
    <!-- 映射 Order 表的基本字段 -->
    <id property="orderId" column="order_id"/>
    <result property="orderNumber" column="order_number"/>
    <result property="customerId" column="customer_id"/>
    <result property="orderDate" column="order_date"/>

    <!-- 一对多关系:Order 包含多个 OrderItem -->
    <collection property="orderItems" ofType="OrderItem">
        <id property="itemId" column="item_id"/>
        <result property="orderId" column="order_id"/>
        <result property="productName" column="product_name"/>
        <result property="quantity" column="quantity"/>
        <result property="price" column="price"/>
    </collection>
</resultMap>
  • property="orderItems":对应 Order 类中的 orderItems 属性。
  • ofType="OrderItem":表示集合中的元素类型是 OrderItem

3.2 编写 SQL 查询

使用 LEFT JOINOrders 表和 OrderItems 表连接起来,确保即使某个订单没有订单项,也能查询到订单信息。

<select id="getOrderWithItems" resultMap="OrderResultMap">
    SELECT 
        o.order_id, o.order_number, o.customer_id, o.order_date,
        i.item_id, i.product_name, i.quantity, i.price
    FROM Orders o
    LEFT JOIN OrderItems i ON o.order_id = i.order_id
    WHERE o.order_id = #{orderId}
</select>
  • 使用 LEFT JOIN 是为了确保即使某个订单没有订单项,也能返回订单信息。
  • #{orderId} 是传入的参数。

3.3 Java 接口

在 Java 接口中定义方法:

public interface OrderMapper {
    Order getOrderWithItems(@Param("orderId") int orderId);
}

4. 查询结果

假设数据库中有以下数据:

Orders

order_idorder_numbercustomer_idorder_date
1ORDER0011012023-10-01
2ORDER0021022023-10-02

OrderItems

item_idorder_idproduct_namequantityprice
11Product A2100.00
21Product B150.00
32Product C3200.00

调用 getOrderWithItems(1) 后,返回的 Order 对象如下:

Order {
    orderId: 1,
    orderNumber: "ORDER001",
    customerId: 101,
    orderDate: "2023-10-01",
    orderItems: [
        OrderItem {
            itemId: 1,
            orderId: 1,
            productName: "Product A",
            quantity: 2,
            price: 100.00
        },
        OrderItem {
            itemId: 2,
            orderId: 1,
            productName: "Product B",
            quantity: 1,
            price: 50.00
        }
    ]
}

5. 一对多查询的优化

如果查询结果较大,可能会产生性能问题(如 N+1 查询问题)。可以通过以下方式优化:

5.1 使用 LEFT JOIN 一次性加载

如上面的示例,使用 LEFT JOIN 一次性加载所有数据,避免多次查询。

5.2 分步查询

如果数据量较大,可以使用分步查询(嵌套查询):

<resultMap id="OrderResultMap" type="Order">
    <id property="orderId" column="order_id"/>
    <result property="orderNumber" column="order_number"/>
    <result property="customerId" column="customer_id"/>
    <result property="orderDate" column="order_date"/>

    <!-- 分步查询:通过 order_id 查询 OrderItems -->
    <collection property="orderItems" ofType="OrderItem" select="selectOrderItemsByOrderId" column="order_id"/>
</resultMap>

<select id="selectOrderItemsByOrderId" resultType="OrderItem">
    SELECT item_id, order_id, product_name, quantity, price
    FROM OrderItems
    WHERE order_id = #{orderId}
</select>

<select id="getOrderWithItems" resultMap="OrderResultMap">
    SELECT order_id, order_number, customer_id, order_date
    FROM Orders
    WHERE order_id = #{orderId}
</select>
  • select="selectOrderItemsByOrderId":指定嵌套查询的方法。
  • column="order_id":将当前查询的 order_id 作为参数传递给嵌套查询。

6. 总结

  • 一对多查询在 MyBatis 中通过 <collection> 标签实现。
  • 可以使用 LEFT JOIN 一次性加载数据,也可以使用分步查询优化性能。
  • 确保实体类和数据库表的结构正确映射。
  • 通过 resultMap 可以灵活地处理复杂的对象关系。

通过以上方法,你可以在 MyBatis 中轻松实现一对多查询,并灵活应对不同的业务需求。

相关文章:

  • 什么是AI?AI能对我们生活产生哪些影响?
  • 基于Python的端口扫描器和目录扫描工具实现方案,结合机器学习进行指纹识别
  • Kubernetes学习笔记-IDEA开发工具本地调试
  • 离线服务器ollama新增qwen2:0.5b模型
  • 从零手工撸写个人工神经元网络(解决异或问题)Python+c++结构化
  • 江科大51单片机笔记【14】LCD1602(上)
  • 操作系统知识点27
  • 双 Token 无感刷新机制在前后端分离架构中实现
  • 【计量地理学】实验三 地理数据的基本统计分析
  • Unity使用自定义类的List在Inspector面板上显示异常(2021.3.4)
  • Appium等待机制--强制等待、隐式等待、显式等待
  • 工具(十二):Java导出MySQL数据库表结构信息到excel
  • 使用DeepSeek完成一个简单嵌入式开发
  • Apache Tomcat漏洞,对其进行升级
  • 前端及后端实现csv文件下载功能
  • 鸿蒙Next开发与实战经验总结
  • MicroPython 智能硬件开发完整指南
  • 《网络应用监测:Netinside的助力企业网络运维》
  • 使用Beanshell前置处理器对Jmeter的请求body进行加密
  • Ubuntu20.04安装运行DynaSLAM
  • 宿州网站建设优化/域名检测查询
  • 快速做效果图的网站叫什么软件/游戏推广话术
  • 温州哪里有网站建设/宁波seo网站排名优化公司
  • 没有网站怎么做cpa赚钱/搜索引擎营销经典案例
  • wordpress制作表单/seo 知乎
  • 国内做涂装生产线网站/网站自动提交收录