一文搞懂ResultMap映射三板斧
共 6638字,需浏览 14分钟
·
2021-09-01 13:30
MyBatis在查询中进行select映射的时候,返回类型可以用ResultType
,也可以用ResultMap
,ResultType是直接表示返回类型的,而ResultMap则是对外部ResultMap的引用,但是ResultType跟ResultMap是不能同时存在的。
什么意思呢?我们先大概梳理下ResultType的功能并说明它现在的不足。
1、ResultType
ResultType
可以直接返回给出的返回值类型,比如String
、int
、Map
,等等,其中返回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>
巨人的肩旁
公众号回复:Java全套、Java架构、大数据、电子书、算法和刷题笔记、面经,即可获得对应的学习资源。
往期推荐