下面我来详细讲解“Mybatis一对多查询的两种姿势(值得收藏)”的完整攻略,其中包含两个示例。
概述
Mybatis作为Java开发中热门的ORM框架之一,其支持的一对多查询功能使用起来相对简单,但是需要掌握一些技巧才能发挥出它的优势。本文将介绍Mybatis中一对多查询的两种姿势,旨在帮助开发人员更好地掌握这一功能。
前置条件
在使用Mybatis一对多查询功能前,需要确保以下条件已经满足:
- 已经配置好Mybatis的环境和数据源;
- 数据库中存在两个表,其中一个表的主键作为另一个表的外键,即一对多关系。
姿势一:使用嵌套查询
嵌套查询是Mybatis一对多查询的一种常用方法。它能够将多条SQL查询语句组合在一起,以一次查询的方式返回多个结果。
下面以一个订单和订单详情表为例进行演示。其中订单表的主键id作为订单详情表的外键order_id。
数据库表结构
CREATE TABLE `order` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`order_no` VARCHAR(20) NOT NULL,
`user_id` INT(11) NOT NULL,
`create_time` DATETIME NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `order_detail` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`order_id` INT(11) NOT NULL,
`product_name` VARCHAR(50) NOT NULL,
`product_price` DECIMAL(10,2) NOT NULL,
PRIMARY KEY (`id`)
);
实体类
订单实体类Order和订单详情实体类OrderDetail的代码如下:
public class Order {
private int id;
private String orderNo;
private int userId;
private Date createTime;
private List<OrderDetail> orderDetails; // 多个订单详情
// 省略 getter 和 setter 方法
}
public class OrderDetail {
private int id;
private int orderId;
private String productName;
private BigDecimal productPrice;
// 省略 getter 和 setter 方法
}
Mybatis Mapper文件配置
在Mybatis Mapper文件中定义两个查询语句,其中一个查询语句查询订单信息,另一个查询语句查询订单详情信息。然后在订单信息查询语句中通过嵌套查询的方式查询订单详情信息。
<!-- 查询订单信息 -->
<select id="getOrder" parameterType="int" resultMap="orderResultMap">
select * from order where id = #{id}
</select>
<!-- 查询订单详情信息 -->
<select id="getOrderDetailList" parameterType="int" resultMap="orderDetailResultMap">
select * from order_detail where order_id = #{orderId}
</select>
<!-- 定义 ResultMap -->
<resultMap id="orderResultMap" type="Order">
<id property="id" column="id"/>
<result property="orderNo" column="order_no" />
<result property="userId" column="user_id" />
<result property="createTime" column="create_time" />
<!-- 嵌套查询,查询订单详情信息 -->
<collection property="orderDetails" ofType="OrderDetail" select="getOrderDetailList"/>
</resultMap>
<resultMap id="orderDetailResultMap" type="OrderDetail">
<id property="id" column="id"/>
<result property="orderId" column="order_id" />
<result property="productName" column="product_name" />
<result property="productPrice" column="product_price" />
</resultMap>
示例代码
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
Order order = orderMapper.getOrder(1024);
System.out.println(order.getOrderNo());
for (OrderDetail orderDetail : order.getOrderDetails()) {
System.out.println(orderDetail.getProductName());
}
} finally {
sqlSession.close();
}
姿势二:使用Mybatis-Plus
Mybatis-Plus是Mybatis框架的增强工具包。它为Mybatis提供了更加便捷的查询方法。Mybatis-Plus内置了分页、乐观锁、通用CRUD操作以及一对多、多对一等复杂SQL查询操作。关于Mybatis-Plus的详细使用可以参考官方文档。
下面以Mybatis-Plus为例进行演示。仍然使用上述订单表和订单详情表,但是在之前的示例中,需要进行一些修改以适应Mybatis-Plus的查询方式。
Maven 依赖
在 Maven 项目的 pom.xml 中添加 Mybatis-Plus 的依赖:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.1</version>
</dependency>
实体类
订单实体类Order和订单详情实体类OrderDetail的代码如下。在订单实体类中包含了 @TableField 注解来映射一对多关系,其中 value 字段为 OrderDetail 的表名,el 字段为关联条件。
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class Order implements Serializable {
// 主键ID
private Integer id;
// 订单号
private String orderNo;
// 用户ID
private Integer userId;
// 下单时间
private LocalDateTime createTime;
// 多个订单详情
@TableField(exist = false)
private List<OrderDetail> orderDetailList;
}
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class OrderDetail implements Serializable {
// 主键ID
private Integer id;
// 订单ID
private Integer orderId;
// 商品名称
private String productName;
// 商品价格
private BigDecimal productPrice;
}
Mybatis-Plus Mapper 接口
定义 OrderMapper,它继承了Mybatis-Plus提供的 BaseMapper。通过使用该类提供的 selectJoin 接口,在查询订单信息时自动关联查询订单详情信息,即可得到一对多查询的结果。
@Mapper
public interface OrderMapper extends BaseMapper<Order> {
@Select("select o.*, od.id as od_id, od.product_name as od_product_name, od.product_price as od_product_price from `order` o left join order_detail od on o.id = od.order_id where o.id = #{id}")
List<Order> selectJoin(Integer id);
}
示例代码
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
List<Order> orderList = orderMapper.selectJoin(1024);
for (Order order : orderList) {
System.out.println(order.getOrderNo());
for (OrderDetail orderDetail : order.getOrderDetailList()) {
System.out.println(orderDetail.getProductName());
}
}
} finally {
sqlSession.close();
}
总结
以上就是Mybatis一对多查询的两种姿势。嵌套查询适用于较为简单的一对多查询,使用起来简单方便,但是需要手动编写嵌套查询SQL语句。使用Mybatis-Plus则更为便捷,而且无需手动编写SQL语句,只需通过 BaseMapper 提供的 selectJoin 接口即可立即查询到一对多的结果。具体使用仍需根据实际情况具体分析和选择。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Mybatis一对多查询的两种姿势(值得收藏) - Python技术站