【DB系列】Mybatis之ResultMap、ResultType返回结果使用姿势

文章目录
  1. I. 环境配置
    1. 1. 项目配置
    2. 2. 数据库表
  2. II. ResultMap & ResultType介绍
    1. 1. 使用区别
    2. 2. 实例演示
    3. 3. 测试验证
    4. 4. 小结
  3. III. 不能错过的源码和相关知识点
    1. 0. 项目
    2. 1. 微信公众号: 一灰灰Blog

在使用mybatis进行数据库操作时,如果希望将返回结果映射为项目中定义的实体对象Entity时,ResultMap与ResultType就很重要了;它们两的主要区别在于ResultType指定指定实体对象,ResultMap则定义数据库字段与实体的映射关系

接下来通过简单的实例来看一下这两种的使用姿势

I. 环境配置

我们使用SpringBoot + Mybatis + MySql来搭建实例demo

  • springboot: 2.2.0.RELEASE
  • mysql: 5.7.22

1. 项目配置

1
2
3
4
5
6
7
8
9
10
11
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>

核心的依赖mybatis-spring-boot-starter,至于版本选择,到mvn仓库中,找最新的

另外一个不可获取的就是db配置信息,appliaction.yml

1
2
3
4
5
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password:

2. 数据库表

用于测试的数据库

1
2
3
4
5
6
7
8
9
10
CREATE TABLE `money` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL DEFAULT '' COMMENT '用户名',
`money` int(26) NOT NULL DEFAULT '0' COMMENT '钱',
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=551 DEFAULT CHARSET=utf8mb4;

II. ResultMap & ResultType介绍

1. 使用区别

ResultMap:

  • 当数据库的字段与定义的实体对象不一致时(如下划线转驼峰,命名不一致等)通过<ResultMap>标签来定义映射关系,然后在sql查询标签中,通过resultMap来指定

ResultType:

  • db中的字段直接与实体对象进行映射时,选择ResultType,其value为实体类的全路径

2. 实例演示

注意上面的表结构,是以下划线的命名方式,接下来定义一个驼峰格式的实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MoneyPo {
private Integer id;

private String name;

private Long money;

private Integer isDeleted;

private Timestamp createAt;

private Timestamp updateAt;
}

基于上面这个case,很明显当我们使用查询时,返回结果就需要做一个映射,此时就可以使用<ResultMap>方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<resultMap id="BaseResultMap" type="com.git.hui.boot.mybatis.entity.MoneyPo">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="money" property="money" jdbcType="INTEGER"/>
<result column="is_deleted" property="isDeleted" jdbcType="TINYINT"/>
<result column="create_at" property="createAt" jdbcType="TIMESTAMP"/>
<result column="update_at" property="updateAt" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="money_po">
id, name, money, is_deleted, create_at, update_at
</sql>

<select id="queryByName" parameterType="java.lang.String" resultMap="BaseResultMap">
select * from money where `name` = #{name}
</select>

注意上面的select标签,通过resultMap来实现表字段与实体对象的转换关系(通过<resultMap>标签内的<result>来定义映射关系)

除了使用上面这种方式之外,也可以通过resultType来指定返回结果为Map,同样是可行的

1
2
3
<select id="queryMapsByName"  parameterType="java.lang.String" resultType="java.util.HashMap">
select * from money where `name` = #{name}
</select>

对应的mapper接口内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Mapper
public interface MoneyMapperV4 {
/**
* int类型,最终的sql中参数替换的也是int
* @param name
* @return
*/
List<MoneyPo> queryByName(@Param("name") String name);

/**
* 注意返回结果
*
* @param name
* @return
*/
List<HashMap<String, Object>> queryMapsByName(@Param("name") String name);
}

3. 测试验证

1
2
3
4
5
6
7
8
9
@Autowired
private MoneyMapperV4 moneyMapperV4;

public void testResQuery() {
List<MoneyPo> list = moneyMapperV4.queryByName("一灰灰blog");
System.out.println(list);
List<HashMap<String, Object>> mapList = moneyMapperV4.queryMapsByName("一灰灰blog");
System.out.println(mapList);
}

输出结果如下

1
2
[MoneyPo(id=1, name=一灰灰blog, money=100, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0, cnt=null, bank=null)]
[{is_deleted=false, money=100, name=一灰灰blog, update_at=2019-04-18 17:01:40.0, id=1, create_at=2019-04-18 17:01:40.0}]

请注意上面的输出,返回结果是Map时,key和db中的字段名完全一致

其次也可以从Mapper接口的返回定义上可以看出,虽然最终返回的是列表,但是我们定义的resultMap, resultType,都是对应的单个实体的映射关系

如何理解上面这句话呢?

  • 如果上面的sql改成只获取id,那么返回结果应该是定义为longe而不是List
1
2
3
<select id="queryIdByName" resultType="long">
select id from money where `name` = #{name}
</select>

对应的mapper接口如下

1
List<Long> queryIdByName(String name);

4. 小结

ResultMap

  • 当希望实现sql返回的对象与项目中的实体类实现关联映射时,可以考虑通过resumtMap来实现

ResultType

  • 指定返回实体类型,可以是基础对象(long, int…) 也可以是Map,当指定一个具体的POJO时,db的表字段与pojo的field全名匹配映射

III. 不能错过的源码和相关知识点

0. 项目

系列博文:

1. 微信公众号: 一灰灰Blog

尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

一灰灰blog


打赏 如果觉得我的文章对您有帮助,请随意打赏。
分享到