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 ...
随机推荐
- vue-eahars生产编译报错
{ test: /\.js$/, loader: 'babel-loader', include: [resolve('src'), resolve('test'), resolve('node_mo ...
- Linux的启动过程及init进程
Linux下有三个特殊进程: idle进程(pid=0)idle进程其前身是系统创建的第一个进程,0号进程,也唯一一个没有通过fork()或者kernel_thread产生的进程,由系统自动创建,运行 ...
- Java基本概念:面向对象
一.简介 面向过程的思维模式是简单的线性思维,思考问题首先陷入第一步做什么.第二步做什么的细节中. 面向对象的思维模式说白了就是分类思维模式.思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独 ...
- 8.Vue组件三---slot插槽
主要内容: 1. 什么是插槽 2. 组件的插槽 3. 插槽的使用方法 4. 插槽的具名 5. 变量的作用域 6. slot的作用域 一. 什么是插槽呢? 1. 生活中的插槽有哪些呢? usb插槽, ...
- Python切换版本工具pyenv
目录 安装pyenv 安装与查看py版本 切换py版本 结合ide使用示例 和virtualenv的一些区别 参考文献 使用了一段时间,我发现这玩意根本不是什么神器,简直就是垃圾,安装多版本总是失败, ...
- React源码 commit阶段详解
转: React源码 commit阶段详解 点击进入React源码调试仓库. 当render阶段完成后,意味着在内存中构建的workInProgress树所有更新工作已经完成,这包括树中fiber节点 ...
- Hi3559AV100外接UVC/MJPEG相机实时采图设计(三):V4L2接口通过MPP平台输出
可以首先参考前面两篇文章: Hi3559AV100外接UVC/MJPEG相机实时采图设计(一):Linux USB摄像头驱动分析: https://www.cnblogs.com/iFrank/p/1 ...
- Reincarnation Without New Body(RWNB): Basic Theory and Baseline 现世转生基本理论及简单操作
Abstract 投胎学是一门高深的学问,不仅没有现存的理论,也没有过往的经验.根据种种猜测,投胎后前世的记忆也不能保留,造成了很大的不方便.在本文中,我们绕过了投胎需要"来世"的 ...
- Linux下找出吃内存的方法总结
Linux下查询进程占用的内存方法总结,假设现在有一个「php-cgi」的进程 ,进程id为「25282」. 现在想要查询该进程占用的内存大小.linux命令行下有很多的工具进行查看,现总结常见的几种 ...
- windows下MySQL如何完全卸载并安装行的版本
卸载本地mysql之前,请务必要先将需要的数据库备份 停止mysql 服务 windows键-->搜索服务 找到mysql 服务,并停止他 卸载mysql server 在控制面板--程序 找到 ...