Mybatis的resultMap标签介绍
说明:在Mybatis中,resultMap 标签可以用于SQL查询后的封装数据,本文用两个场景介绍 resultMap 标签的使用。
搭建环境
先搭一个Demo,pom如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.12</version>
<relativePath/>
</parent>
<groupId>com.hezy</groupId>
<artifactId>mybatis_result_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<!--mybatis依赖-->
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!--测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
三个实体类,对应关系是:一个订单对应一个用户,一个订单对应多个订单详情
(订单)
import lombok.Data;
/**
* 订单
*/
@Data
public class Order {
private Long orderId;
private Long userId;
private String orderTitle;
}
(用户)
import lombok.Data;
/**
* 用户
*/
@Data
public class User {
private Long userId;
private String username;
private String password;
}
(订单详情)
import lombok.Data;
import java.math.BigDecimal;
/**
* 订单详情
*/
@Data
public class OrderDetail {
private Long orderDetailId;
private Long orderId;
private String productName;
private BigDecimal productPrice;
}
数据库数据如下:
一对多关系
现在,我们根据订单ID查询订单,并且把对应的订单详情也关联查出来,SQL如下:
select t1.order_id,
t1.order_title,
t1.user_id,
t2.order_detail_id,
t2.product_name,
t2.product_price
from tb_order t1
left join tb_order_detail t2 on t1.order_id = t2.order_id
where t1.order_id = 1;
结果如下:
那么,我们对应的VO,应该是下面这样
import com.hezy.pojo.entity.OrderDetail;
import lombok.Data;
import java.util.List;
/**
* 订单和订单详情VO
*/
@Data
public class OrderAndDetailVO {
private Long orderId;
private Long userId;
private String orderTitle;
/**
* 一个订单对应多个订单详情
*/
private List<OrderDetail> orderDetails;
}
如何把上面的SQL记录,按照 一个订单对应多个订单详情的关系
封装到VO对象中。这时,就需要使用 resultMap
标签,如下:
<!--处理返回结果-->
<resultMap id="selectDetailById" type="com.hezy.pojo.vo.OrderAndDetailVO">
<result column="order_id" property="orderId" />
<result column="user_id" property="userId" />
<result column="order_title" property="orderTitle" />
<collection property="orderDetails" ofType="com.hezy.pojo.entity.OrderDetail">
<id column="order_detail_id" property="orderDetailId" />
<result column="order_id" property="orderId" />
<result column="product_name" property="productName" />
<result column="product_price" property="productPrice" />
</collection>
</resultMap>
<!--查询,返回结果使用对应resultMap标签处理-->
<select id="selectOrderAndDetailById" resultMap="selectDetailById">
select t1.order_id,
t1.order_title,
t1.user_id,
t2.order_detail_id,
t2.product_name,
t2.product_price
from tb_order t1
left join tb_order_detail t2 on t1.order_id = t2.order_id
where t1.order_id = #{orderId}
</select>
其中的 resultMap 可以分开下成下面这样,效果相同
<resultMap id="selectOrderByIdResultMap" type="com.hezy.pojo.entity.Order">
<result column="order_id" property="orderId" />
<result column="order_title" property="orderTitle" />
</resultMap>
<resultMap id="selectById" type="com.hezy.pojo.vo.OrderVO" extends="selectOrderByIdResultMap">
<collection property="orderDetails" ofType="com.hezy.pojo.entity.OrderDetail">
<id column="order_detail_id" property="orderDetailId"></id>
<result column="order_id" property="orderId"></result>
<result column="product_name" property="productName"></result>
<result column="product_price" property="productPrice"></result>
</collection>
</resultMap>
测试一下
@Test
public void selectTest2() {
OrderAndDetailVO orderAndDetailVO = orderMapper.selectOrderAndDetailById(1L);
System.out.println("orderAndDetailVO = " + orderAndDetailVO);
}
可以看到,完全封装进来了
一对一关系
前面一对多关系是比较常见的,比如购物车场景、分组场景都是一对多的,一对一比较少见,这里我假设订单表里冗余了用户信息,表示某个订单只能所属于某一个用户,查询订单的同时,将该订单对应的用户信息也查出来。
对应的SQL如下:
select t1.order_id,
t1.order_title,
t2.user_id,
t2.username,
t2.password
from tb_order t1
left join tb_user t2 on t1.user_id = t2.user_id
where t1.order_id = 1
结果如下:
那对应的VO如下:
import com.hezy.pojo.entity.User;
import lombok.Data;
/**
* 订单和用户信息VO
*/
@Data
public class OrderAndUserVO {
private Long orderId;
private String orderTitle;
private User user;
}
使用 resultMap 封装查询结果,如下,使用 association
标签
<!--处理返回结果-->
<resultMap id="selectUserById" type="com.hezy.pojo.vo.OrderAndUserVO">
<result column="order_id" property="orderId" />
<result column="order_title" property="orderTitle" />
<association property="user" javaType="com.hezy.pojo.entity.User">
<id column="user_id" property="userId" />
<result column="username" property="username" />
<result column="password" property="password" />
</association>
</resultMap>
<select id="selectOrderAndUserById" resultMap="selectUserById">
select t1.order_id,
t1.order_title,
t2.user_id,
t2.username,
t2.password
from tb_order t1
left join tb_user t2 on t1.user_id = t2.user_id
where t1.order_id = #{orderId}
</select>
测试一下
@Test
public void selectTest3() {
OrderAndUserVO orderAndUserVO = orderMapper.selectOrderAndUserById(2L);
System.out.println("orderAndUserVO = " + orderAndUserVO);
}
可以看到,也封装进来了。
另外
在阿里巴巴Java代码规范中,有下面这条
简单说,JavaBean中表示是否的属性命名,不要以“is”开头,但MySQL中表示是否关系的字段必须以“is”开头,所以查询后需要使用resultMap映射。
博主在日常工作中,遇到过这样的情况,VO对象中表示是否启用的字段名是isActivity,返回给前端的数据无故多出来了一个activity字段,就是由“isActivity"字段衍生出来的。另外遇到一些序列化错误,也是因为JavaBean中有这样的属性。
总结
本文介绍了Mybatis中resultMap标签的使用