一文搞懂ResultMap映射三板斧

小郎码知答

共 6638字,需浏览 14分钟

 ·

2021-09-01 13:30

MyBatis在查询中进行select映射的时候,返回类型可以用ResultType,也可以用ResultMap,ResultType是直接表示返回类型的,而ResultMap则是对外部ResultMap的引用,但是ResultType跟ResultMap是不能同时存在的。

什么意思呢?我们先大概梳理下ResultType的功能并说明它现在的不足。

1、ResultType

ResultType可以直接返回给出的返回值类型,比如StringintMap,等等,其中返回List也是将返回类型定义为Map,然后mybatis会自动将这些map放在一个List中,ResultType还可以是一个对象,举例如下:

(1)返回常见的类型

  <select id="getLogCount" ResultType="int">
    select COUNT(*) from AttLog where attTime = #{attTime} and userId = #{userId};
  </select>

(2)返回Map

MyBatis支持将查询的数据封装成Map

  • 如果查询的结果是一条,我们可以把查询的数据以{表字段名, 对应的值}方式存入到Map中。
 <!-- 注意这里的 ResultType 返回值类型是 'map'-->
    <select id="getEmpAsMapById" ResultType="map">
        select * from t_employee where id = #{id}
    </select>
  • 如果查询的结果是多条数据,我们也可以把查询的数据以{表中某一字段名, JavaBean}方式来封装成Map
    <!--注意 ResultType 返回值类型,不再是 'map',而是 Map 的 value 对应的 JavaBean 类型-->
    <select id="getAllEmpsAsMap" ResultType="com.simon.employee">
        select * from t_employee
    </select>

(3)返回对象

对于SQL语句查询出的字段在相应的pojo中必须有和它相同的字段对应。

但是,如果列名没有精确匹配,你可以在列名上使用 select 字句的别名(一个 基本的 SQL 特性)来匹配标签。

<select id="selectUsers" parameterType="int" ResultType="User">
  select
    user_id             as "id",
    user_name           as "userName",
    hashed_password     as "hashedPassword"
  from some_table
  where id = #{id}
</select>

(4)返回一个List

有时候我们要查询的数据不止一条,比如:模糊查询全表查询等,这时候返回的数据可能不止是一条数据,对于多数据的处理可以存放在List集合中,List集合中存放的是Java Bean

    <!--注意这里的 ResultMap 返回值类型是集合内存储数据的类型,不是 'list' -->
    <select id="getAllEmps" ResultType="com.simon.employee">
        select * from t_employee
    </select>

NOTE

当我们在MyBatis进行查询映射时,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值。因此,当提供的返回类型属性是ResultType时,MyBatis会将Map里面的键值对取出赋给ResultType所指定的对象对应的属性。

ResultType可以把查询结果封装到pojo类型中,但必须pojo类的属性名和查询到的数据库表的字段名一致。如果sql查询到的字段与pojo的属性名不一致,则需要使用ResultMap将字段名和属性名对应起来,进行手动配置封装,将结果映射到pojo中。

事实上,MyBatis的每一个查询映射的返回类型都是ResultMap,只是当提供的返回类型属性是ResultType的时候,MyBatis会自动的把对应的值赋给ResultType所指定对象的属性。

下面,我们就开始学习ResultMap

1、字段映射

字段映射是Mybatis中最简单的映射方式。

比如我们有一个Person类,

@Data
public class Person {
    private String id;
    private String name;
    private String address;
}

如果数据库中表的字段与Person类的属性名称一致,我们就可以使用resultType来返回。

如果两者不对应,那么就需要ResultMap来映射不一样的字段。

<resultMap type="person" id="BaseResultMap">
    <!-- column:库表的字段名 property:实体类里的属性名 -->
    <id column="person_id" property="id" />
    <result column="persion_name" property="name" />
    <result column="person_address" property="address" />
</resultMap>

id:resultMap:的唯一标识

column:库表的字段名

property:实体类里的属性名

上面是比较简单的用法,下面我们看下另外几种标签的用法。

元素名称描述
constructor用于在实例化类时,注入结果到构造方法中
association关联一个对象
collection关联多个对象

2、构造方法constructor

constructor是将sql查询的结果注入到构造方法中

比如,我们在Person类增加了一个构造方法。

public Person(String id, String name) {
 this.id = id;
 this.username = name;
}

我们就需要在resultMap中定义constructor元素:

<resultMap id="getPersonByIdMap" type="Person">
 <constructor>
  <idArg column="id" name="id" javaType="string"></idArg>
  <arg column="username" name="name" javaType="string"></arg>
 </constructor>
</resultMap>

3、association

然而在实际的业务中,表之间是相互关联的,如一个用户存在一个角色。

@Data
public class Person {
   private String id;
    private String name;
    private String address;
    private Role role;
}

如果要查询单个用户及用户的角色信息,我们就需要想办法把两者关联起来

因此,我们除了使用ResultMap标签外,还需要使用关联标签association

<resultMap id="BaseResultMap" type="Person">
 <id column="person_id" property="id" />
    <result column="persion_name" property="name" />
    <result column="person_address" property="address" />
    
 <association property="role" javaType="Role">
  <id column="role_id" property="id"></id>
  <result column="role_name" property="name"></result>
 </association>
</resultMap>

4、collection

在真实的业务中,一个表不仅仅对应一个表,而是一对多的情况。

因此,我们可以使用collection标签来处理这种情况。

collection就像association 那样,我们使用嵌套查询,或者从连接中嵌套结果集。

比如一个用户存在多个角色。

@Data
public class Person {
    //省略用户属性...
 
    //角色信息
    private List<Role> roles;
}

使用collection处理有多个关联。

<resultMap id="BaseResultMap" type="Person">
 <id column="person_id" property="id" />
    <result column="persion_name" property="name" />
    <result column="person_address" property="address" />
 
 <collection property="role" javaType="Role">
  <id column="role_id" property="id"></id>
  <result column="role_name" property="name"></result>
 </collection>
</resultMap>

巨人的肩旁

[1]https://blog.csdn.net/bear_wr/article/details/52383840
[2]https://juejin.cn/post/6844903858477481992
[3]https://blog.csdn.net/codejas/article/details/79520246

公众号回复Java全套Java架构大数据电子书算法和刷题笔记面经,即可获得对应的学习资源。

往期推荐

一文带你彻底搞懂Cookie、Session和Token

机械硕士转计算机,我是怎么做的?

so easy,一文拿下Git!

Typora+PicGo+Gitee搭建博客写作环境

没有Linux服务器,该如何学习Linux呢?

浏览 70
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报