Mybatis注解开发进阶之复杂的关联查询
在MyBatis注解式开发里,处理复杂的关联查询可通过多种方式,本文将结合实际场景,详细介绍几种常见的处理方法。
本文目录
- 1. 使用 @Results 和 @Result注解进行手动映射
- 2. 使用 @SelectProvider动态生成 SQL
1. 使用 @Results 和 @Result注解进行手动映射
当涉及到关联查询时,数据库表的字段和实体类的属性可能无法自动映射,这时可以使用 @Results
和 @Result
注解手动指定映射关系。
假设有 Order
(订单)和 Product
(商品)两个实体,一个订单可以包含多个商品,需要查询订单信息并关联查询出商品信息。
实体类定义:
// Order 类
@Data
public class Order {
private Long id;
private String orderNo;
private List<Product> products;
}
// Product 类
@Data
public class Product {
private Long id;
private String name;
private double price;
}
Mapper接口:
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface OrderMapper {
@Select("SELECT o.id, o.order_no, p.id as product_id, p.name as product_name, p.price as product_price " +
"FROM orders o " +
"JOIN order_items oi ON o.id = oi.order_id " +
"JOIN products p ON oi.product_id = p.id " +
"WHERE o.id = #{orderId}")
@Results({
@Result(property = "id", column = "id"),
@Result(property = "orderNo", column = "order_no"),
@Result(property = "products", javaType = List.class,
many = @Many(select = "com.shop.mapper.ProductMapper.getProductsByOrderId"))
})
Order getOrderWithProducts(Long orderId);
}
// ProductMapper 接口
@Mapper
public interface ProductMapper {
@Select("SELECT * FROM products WHERE id IN (SELECT product_id FROM order_items WHERE order_id = #{orderId})")
List<Product> getProductsByOrderId(Long orderId);
}
@Results
注解用于手动指定结果集的映射关系。
@Result
注解中,property
表示实体类的属性名,column
表示数据库表的列名。
@Many
注解用于处理一对多的关联关系,select
属性指定了关联查询的方法。
2. 使用 @SelectProvider动态生成 SQL
对于复杂的关联查询,SQL 语句可能会根据不同的条件动态变化,这时可以使用 @SelectProvider
注解动态生成 SQL。比如,如果需要根据用户输入的条件,动态查询订单及其关联的商品信息。
Mapper接口:
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface OrderMapper {
@SelectProvider(type = OrderSqlProvider.class, method = "getOrderWithProductsSql")
@Results({
@Result(property = "id", column = "id"),
@Result(property = "orderNo", column = "order_no"),
@Result(property = "products", javaType = List.class,
many = @Many(select = "com.example.shop.ProductMapper.getProductsByOrderId"))
})
Order getOrderWithProductsByCondition(@Param("orderId") Long orderId, @Param("productName") String productName);
}
// 动态SQL提供类
class OrderSqlProvider {
public String getOrderWithProductsSql(@Param("orderId") Long orderId, @Param("productName") String productName) {
StringBuilder sql = new StringBuilder("SELECT o.id, o.order_no, p.id as product_id, p.name as product_name, p.price as product_price " +
"FROM orders o " +
"JOIN order_items oi ON o.id = oi.order_id " +
"JOIN products p ON oi.product_id = p.id " +
"WHERE 1 = 1");
if (orderId != null) {
sql.append(" AND o.id = #{orderId}");
}
if (productName != null && !productName.isEmpty()) {
sql.append(" AND p.name LIKE CONCAT('%', #{productName}, '%')");
}
return sql.toString();
}
}
@SelectProvider
注解指定了提供 SQL 语句的类和方法。
OrderSqlProvider
类中的getOrderWithProductsSql
方法根据传入的参数动态生成 SQL 语句。