9. resultMap 结果映射集
@Data
public class CreditCard extends BankCard {
/**
* 消费额度
*/
private String creditLine;
}
@Data
public class DebitCard extends BankCard {
/**
* 存款金额
*/
private String deposit;
}
resultmap是mybatis中最复杂的元素之一,它描述如何从结果集中加载对象,主要作用是定义映射规则、级联的更新、定制类型转化器。
resultmap构成元素

1.id和result元素
以User类为例:
class User{
private int userId;
private String name;
public User(long userId,String name){
this.userId = userId;
this.name = name;
}
}
id、result是最简单的映射,id为主键映射;result其他基本数据库表字段到实体类属性的映射。resultmap的xml如下:
<resultMap type="User" id="userMap">
<id property="UserId" column="user_id" javaType="int" jdbcType="int"/>
<result property="name" column="name" javaType="String" jdbcType="VARCHAR"/>
</resultMap>
id、result语句属性配置细节:

2. CONSTRUCTOR 构造器
在resultMap中,通常使用id、result子元素把Java实体类的属性映射到数据库表的字段上。但是如果在遇到JavaBean没有无参构造函数时,我还需要使用构造器元素实现一个JavaBean的实例化和数据注入。
再以User为例,那么对应的resultmap就需要添加构造器:
<constructor>
<idArg column="user_id" javaType="long"/>
<arg column="name" javaType="String"/>
</constructor>
定义java实体类的属性映射到数据库表的字段上。我们也可以使用实体类的构造方法来实现值的映射,这是通过构造方法参数的书写的顺序来进行赋值的。
这样MyBatis就知道需要用这个构造方法构造了。
3.结果集处理方法
1. 使用map储存结果集
一般情况下,所有select语句都可以使用map储存,但是使用map就意味着可读性的下井,所以这不是推荐的方式。
<select id="findUserById" parameterType="long" resultType="map">
select user_id ,name form user where user_id=#{userId}
</select>
2. 使用POJO储存结果集(推荐)
一般我们都使用POJO储存查询结果。我们可以使用select自动映射,还可以使用select语句中的resultMap属性配置映射集合,不过需要提前定义resultMap。
那我们就可以将之前的select语句修改:
<select id="findUserById" parameterType="long" resultMap="userMap">
select user_id ,name form user where user_id=#{userId}
</select>
4.级联
在数据库中包含着一对多、一对一的关系。比如说一个人和他的身份证就是一对一的关系,但是他和他的银行卡就是一对多的关系。我们的生活中存在着很多这样的场景。我们也希望在获取这个人的信息的同时也可以把他的身份证信息一同查出,这样的情况我们就要使用级联。在级联中存在3种对应关系。
- 一对一的关系
- 一对多的关系
- 多对多的关系(这种情况由于比较复杂,我们通常会使用双向一对多的关系来降低复杂度)
1.association 一对一级联
我们继续使用User类,同时为其增加一个Card类,人和他的身份证就行成了一对一的关系。我们再创建一个Card类。
@Data
@Alias("card")
public class Card {
private Long id;
private Long userId;
private String name;
private String address;
}
这是需要在User中添加属性Card,这样就形成了一对一的级联。
@Data
@Alias("user")
public class User {
private Long id;
private String username;
private String password;
private String email;
private Card card;
}
这时需要CardMapper提供findCardByUserId(Long userId)方法,定义其映射器如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.changzhen.mybatis.mapper.CardMapper">
<resultMap id="cardMap" type="card">
<id property="id" column="id"></id>
<result property="userId" column="user_id"/>
<result property="name" column="name"/>
<result property="address" column="address"/>
</resultMap> <select id="findCardByUserId" parameterType="long" resultMap="cardMap">
SELECT id, user_id, name, address FROM card WHERE user_id = #{userId}
</select>
</mapper>
有了CardMapper,我们将可以在UserMaper中使用 findCardByUserId 进行级联
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.changzhen.mybatis.mapper.UserMapper">
<select id="getUser" resultMap="userMap" parameterType="long">
SELECT id,username,password,email FROM USER WHERE id=#{id}
</select>
<resultMap id="userMap" type="user">
<id property="id" column="id"/>
<result property="password" column="password"/>
<result property="email" column="email"/>
<association property="card" column="id" select="com.changzhen.mybatis.mapper.CardMapper.findCardByUserId"/>
</resultMap>
通过关联处理,其中select元素指定的sql查询,而column则是指定传递给select的参数,是user对象id。当取出User的时候,MyBatis就知道下面的sql取出我们需要的级联信息。
<association property="card" column="id" select="com.changzhen.mybatis.mapper.CardMapper.findCardByUserId"/>
其中参数是User的值,通过column配置,如果是多个参数则使用逗号隔开。
可以看出执行了两条sql分别查询了User和Card。

2.collection 一对多级联
这一对多的级联,一个身份证可以办理多张银行卡。每个用户对应一个身份证,每个身份证对应多个银行卡。所以这两个级联,分别使用association和collection完成。
- 首先,创建BankCard类,为Card增加bankCardList属性
@Alias("bankCard")
@Data
public class BankCard {
private Long id;
private Long userId;
private String bankName;
private int type;
}
@Data
@Alias("card")
public class Card {
private Long id;
private Long userId;
private String name;
private String address;
private List<BankCard> bankCards;
}
创建BankCardMapper
@Mapper
public interface BankCardMapper {
public List findCreditCardsByUserId(Long userId);
}
xml最简单的映射器
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.changzhen.mybatis.mapper.CreditCardMapper">
<select id="findCreditCardsByUserId" parameterType="long" resultType="creditCard">
SELECT id, user_id, bank_name, type FROM bank_card WHERE user_id = #{userId}
</select>
</mapper>
- 最后在Card映射器中添加collection,一对多级联。
<mapper namespace="com.changzhen.mybatis.mapper.CardMapper">
<resultMap id="cardMap" type="card">
<id property="id" column="id"></id>
<result property="userId" column="user_id"/>
<result property="name" column="name"/>
<result property="address" column="address"/>
<collection property="creditCards" column="id" select="com.changzhen.mybatis.mapper.BankCardMapper.findBankCardsByUserId"/>
</resultMap> <select id="findCardByUserId" parameterType="long" resultMap="cardMap">
SELECT id, user_id, name, address FROM card WHERE user_id = #{userId}
</select>
</mapper>
3.discriminator 鉴别器级联
鉴别器级联是在不公情况下使用不同的POJO。例如,在本例中我们每个人都有好多银行卡,但是银行卡的种类却不同,比如有借记卡(DebitCard)和信用卡(CreditCard),我们需要按需来创建不同的POJO。这时我们就需要在BankCard中添加types属性进行判断,确定使用哪个POJO。
接下来需要创建DebitCard和CreditCard两个继承BankCard的子类
案例
<!--column不做限制,可以为任意表的字段,而property须为type 定义的pojo属性-->
<resultMap id="唯一的标识" type="映射的pojo对象">
<id column="表的主键字段,或者可以为查询语句中的别名字段" jdbcType="字段类型" property="映射pojo对象的主键属性" />
<result column="表的一个字段(可以为任意表的一个字段)" jdbcType="字段类型" property="映射到pojo对象的一个属性(须为type定义的pojo对象中的一个属性)"/>
<association property="pojo的一个对象属性" javaType="pojo关联的pojo对象">
<id column="关联pojo对象对应表的主键字段" jdbcType="字段类型" property="关联pojo对象的主席属性"/>
<result column="任意表的字段" jdbcType="字段类型" property="关联pojo对象的属性"/>
</association>
<!-- 集合中的property须为oftype定义的pojo对象的属性-->
<collection property="pojo的集合属性" ofType="集合中的pojo对象">
<id column="集合中pojo对象对应的表的主键字段" jdbcType="字段类型" property="集合中pojo对象的主键属性" />
<result column="可以为任意表的字段" jdbcType="字段类型" property="集合中的pojo对象的属性" />
</collection>
</resultMap>
参考:https://blog.csdn.net/wuskzuo/article/details/79186144
<select id="findUserById" parameterType="long" resultType="map"> select user_id ,name form user where user_id=#{userId} </select>
9. resultMap 结果映射集的更多相关文章
- Mybatis resultMap空值映射问题解决
Mybatis在使用resultMap来映射查询结果中的列,如果查询结果中包含空值的列(不是null),则Mybatis在映射的时候,不会映射这个字段,例如 查询 name,sex,age,数据库中的 ...
- Mybatis resultMap空值映射问题
参考博客:https://www.oschina.net/question/1032714_224673 http://stackoverflow.com/questions/22852383/how ...
- resultMap自定义映射---8.3.1. 解决列名(表中的字段名称)和实体类中的属性名不一致
1.1.1.1. 步骤一:将驼峰匹配注释掉 --------------测试完成后仍然 回来开启 其他地方可能用到 一旦注释掉驼峰匹配,那么再通过queryUserById查询的结果中,用 ...
- resultMap自定义映射(多对一)
自定义resultMap,处理复杂的表关系,实现高级结果集映射 1) id :用于完成主键值的映射 2) result :用于完成普通列的映射 3) association :一个复杂的类型关联;许多 ...
- Mybatis中多表关联时,怎么利用association优雅写resultMap来映射vo
前言 有好一阵没碰mybatis了,这次的项目基于性能考虑,选了mybatis,写着写着,发现有下面的需求,比如两表联查,取其中各一部分字段,怎么更方便地用vo来接,这里犯了难: 我想的是,因为这个s ...
- resultMap自定义映射(一对多)
collection:处理一对多和多对多的关系 1) POJO中的属性可能会是一个集合对象,我们可以使用联合查询,并以级联属性的方式封装对象.使用collection标签定义对象的封装规则 publi ...
- 深入理解MyBatis的原理(四):映射器的用法
前言:继续深入学习 mybatis 的用法及原理,还是先会用再学习原理. 映射器的主要元素有:select.insert.update.delete.parameterMap(即将被删除,不建议使用) ...
- 《深入浅出MyBatis技术原理与实战》——4. 映射器,5. 动态SQL
4.1 映射器的主要元素 4.2 select元素 4.2.2 简易数据类型的例子 例如,我们需要统计一个姓氏的用户数量.应该把姓氏作为参数传递,而将结果设置为整型返回给调用者,如: 4.2.3 自动 ...
- 二、Mapper映射文件
Mapper映射文件 mapper.xml映射文件主要是用来编写SQL语句的,以及一些结果集的映射关系的编写,还有就是缓存的一些配置等等. 在映射文件里面可以配置以下标签: 元素名称 描述 备注 se ...
随机推荐
- 1102 Invert a Binary Tree——PAT甲级真题
1102 Invert a Binary Tree The following is from Max Howell @twitter: Google: 90% of our engineers us ...
- Eclipse和MyEclipse光标变成黑色块解决办法
今天偶然发现了一个小技巧,O(∩_∩)O~暂且可以这样说吧,我认为喽. 以前经常在编写程序是不知到碰到键盘上的那个键了,或是那几个组合键了,使得Eclipse里的代码光标变成一个黑色块:在这个状态下, ...
- 获取点击元素的id
1.onclick="dianji(this.id)" 传入id到方法里function dianji(id){ //这个就是id}2. $(document).click(fun ...
- redis.conf 配置说明
redis.conf 配置项说明如下: 1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程 daemonize no 2. 当Redis以守护进程方式运行时,R ...
- Newbe.Claptrap 框架入门,第二步 —— 创建项目
接上一篇 Newbe.Claptrap 框架入门,第一步 -- 开发环境准备 ,我们继续了解如何创建一个 Newbe.Claptrap 项目. Newbe.Claptrap 是一个用于轻松应对并发问题 ...
- JDK的下载、安装与配置
一.JDK的下载 1.JDK下载地址:https://www.oracle.com/cn/java/technologies/javase-downloads.html 2.登录Oralce官网:ht ...
- $nextTick解决Vue组件卸载在加载合并的问题
情况是这样的,父子组件都是复选框,点击父组件的复选框,子组件的复选框要显示并全选,取消复选框,子组件隐藏.子组件显隐我用的 v-if ,使用created钩子函数来使子组件处于全选状态. 但是出现的问 ...
- POJ_2533 Longest Ordered Subsequence 【LIS】
一.题目 Longest Ordered Subsequence 二.分析 动态规划里的经典问题.重在DP思维. 如果用最原始的DP思想做,状态转移方程为$DP[i] = max(DP[j] + 1) ...
- Mardown语法
1.什么是Markdown Mardown是一种文本标记语言,使用它,能让我们更加专注于内容的输出,而不是排版样式. 我们平常使用的.txt文档书写的文字是没有样式的,使用Markdown语法就可以给 ...
- 冒泡排序算法的实现(Java)
什么是冒泡排序 冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法.它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小.首字母从Z到A)错误就把他们交换 ...