前言

在Mybatis中,有一个强大的功能元素resultMap。当我们希望将JDBC ResultSets中的数据,转化为合理的Java对象时,你就能感受到它的非凡之处。正如其官方所述的那样:

resultMap元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的长达数千行的代码。ResultMap 的设计思想是,对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了。

一、字段映射

在Mybatis中,最简单的结果映射方式,就是通过类型别名typeAliases来处理。

如果要这样做,那么第一步需要配置实体类包的路径:

mybatis.type-aliases-package=com.xxx.entity

该路径下的所有类,就会被注册到TYPE_ALIASES容器。我们在指定返回值类型的时候,就直接用别名即可。

比如,我们有一个User类:

@Data

public class User {

private String id;

private String username;

private String password;

private String address;

private String email;

}

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

SELECT

u.id,

u.username,

u.password,

u.address,

u.email

FROM

USER u

当然,这是理想状态下,属性和字段名都完全一致的情况。但事实上,不一致的情况是有的,这时候我们的resultMap就要登场了。

如果User类保持不变,但SQL语句发生了变化,将id改成了uid。

SELECT

u.id as uid,

u.username,

u.password,

u.address,

u.email

FROM

USER u

那么,在结果集中,我们将会丢失id数据。这时候我们就可以定义一个resultMap,来映射不一样的字段。

然后,我们把上面的select语句中的resultType修改为resultMap="getUserByIdMap"。

这里面column对应的是数据库的列名或别名;property对应的是结果集的字段或属性。

这就是resultMap最简单,也最基础的用法:字段映射。

下面,我们看看其他几种标签都是怎么应用的。

二、构造方法

如果你希望将结果注入构造方法里,就可以用到constructor元素。

比如,我们的User类增加了一个构造方法:

public User(String id, String name) {

this.id = id+"--------";

this.username = name+"--------";

}

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

其中,column代表数据库字段名称或者别名;name则是构造方法中的参数名称;javaType指定了参数的类型。

如你所想,这样指定构造方法后,我们结果集中的id和username属性都会发生变化。

{

"id": "1001--------",

"username": "后羿--------",

"password": "123456",

"address": "北京市海淀区",

"email": "510273027@qq.com"

}

三、关联

在实际的业务中,我们的用户一般都会有一个角色。那么在User类里面一般也是以一个实体类来表示。

@Data

public class User {

//省略用户属性...

//角色信息 private Role role;

}

我们在查询用户的时候,如果也希望看到它的角色信息,我们会这样来写查询语句:

SELECT

u.id,

u.username,

u.password,

u.address,

u.email,

r.id as 'role_id',

r.name as 'role_name'

FROM

USER u

LEFT JOIN user_roles ur ON u.id = ur.user_id

LEFT JOIN role r ON r.id = ur.role_id

where u.id=#{id}

如上,就要查询单个用户以及用户的角色信息。不过在这里,我们不能用resultType=User来返回。

毕竟,User类中只有一个Role对象,并没有role_id和role_name字段属性。

所以,我们要使用association来关联它们。

最后我们就可以将角色信息一块显示出来:

{

"id": "1001",

"username": "后羿",

"password": "123456",

"address": "北京市海淀区",

"email": "3553154544@qq.com",

"role": {

"id": "3",

"name": "射手"

}

}

事实上,如果你确定关联信息是一对一的情况,有个更简便的方法可以替代association,我们在本文的第五部分-自动填充关联对象再看它是怎么实现的。

四、集合

1、集合的嵌套结果映射

上面我们看到一个用户后羿,它的角色是射手;但大部分时候,我们每个人都不可能只拥有一种角色。所以,我们需要将User类中的角色属性的类型改成List。

@Data

public class User {

//省略用户属性...

//角色信息 private List roles;

}

现在就变成了一个用户对应多个角色,所以就不是简单的association。

因为association处理的是有一个类型的关联;而我们这里是有多个类型的关联,所以就需要用到collection属性。

我们整体的resultMap会变成下面这样:

这样的话,即便你有多个角色也可以被正确显示:

{

"id": "1003",

"username": "貂蝉",

"password": "123456",

"address": "北京市东城区",

"email": "510273027@qq.com",

"roles": [

{

"id": "1",

"name": "中单"

},

{

"id": "2",

"name": "打野"

}

]

}

2、集合的嵌套 Select 查询

在大部分业务系统中,我们都会有一个菜单的表,比如像下面这样,一张Menu表:

这里我们给菜单分为两级。我们给前端返回菜单的时候,也是需要分级的,不可能将这7条数据平级展示。那么,在这里我们的Menu实体类如下:

@Data

public class Menu {

private String id;

private String name;

private String url;

private String parent_id;

private List

}

一级菜单,包含一个二级菜单的列表,这里用childMenu来表示。

SQL语句中,如果没有parent_id字段属性,我们就先查所有的一级菜单:

SELECT

m.id,

m.name,

m.url,

m.parent_id

FROM

m_menu m

where 1=1

and m.parent_id = #{parent_id}

and m.parent_id = '0'

这个查询语句,在不传输任何参数的情况下,我们会得到两条一级菜单的数据。

那么在只调用此方法一次的情况下,怎么把所有的菜单信息查询出来,并按层级展示呢?

我们来看menusMap的定义:

重点来看collection元素:

property="childMenu" 对应的是菜单中的子级菜单列表;

ofType="Menu" 对应返回数据的类型;

select="getMenus" 指定了SELECT语句的id;

column="{parent_id=id}" 则是参数的表达式。

这个collection整体的含义可以这样理解:

通过getMenus这个SELECT语句来获取一级菜单中的childMenu属性结果;在上面的SELECT语句中,需要传递一个parent_id参数;这个参数的值就是一级菜单中的id。

通过这种方式,我们就可以得到已分级的所有菜单信息。

[

{

"id": "1",

"name": "系统管理",

"parent_id": "0",

"childMenu": [

{

"id": "1001",

"name": "用户管理",

"url": "/user",

"parent_id": "1"

},

{

"id": "1002",

"name": "角色管理",

"url": "/role",

"parent_id": "1"

},

{

"id": "1003",

"name": "单位管理",

"url": "/employer",

"parent_id": "1"

}

]

},

{

"id": "2",

"name": "平台监控",

"parent_id": "0",

"childMenu": [

{

"id": "2001",

"name": "系统监控",

"url": "/system/monitor",

"parent_id": "2"

},

{

"id": "2002",

"name": "数据监控",

"url": "/data/monitor",

"parent_id": "2"

}

]

}

]

五、自动填充关联对象

我们知道,在Mybatis解析返回值的时候。

第一步是获取返回值类型,拿到Class对象,然后获取构造器,设置可访问并返回实例,然后又把它包装成MetaObject对象。

从数据库rs中拿到结果之后,会调用MetaObject.setValue(String name, Object value) 来填充对象。

在这过程中,有趣的是,它会以.来分隔这个name属性。

如果name属性中包含.符号,就找到.符号之前的属性名称,把它当做一个实体对象来处理。

可能笔者在这里描述的不够直观,我们还是来看例子。

在本文第三部分中,我们有一个用户对应一个角色的例子。

其中,User类定义如下:

@Data

public class User {

//省略用户属性...

//角色信息 private Role role;

}

在这里,我们无需定义resultMap,直接返回resultType=User即可。不过需要把role信息的别名修改一下,重点是.符号

SELECT

u.id,

u.username,

u.password,

u.address,

u.email,

r.id as 'role.id',

r.name as 'role.name'

FROM

USER u

LEFT JOIN user_roles ur ON u.id = ur.user_id

LEFT JOIN role r ON r.id = ur.role_id

这样,在Mybatis解析到role.id属性的时候,以.符号分隔之后发现,role别名对应的是Role对象,则会先初始化Role对象,并将值赋予id属性。

相关代码如图:

来源:掘金

作者:清幽之地

resultmap的写法_Mybatis中强大的resultMap相关推荐

  1. mybatis collection用法_Mybatis中强大的resultMap

    前言 在Mybatis中,有一个强大的功能元素resultMap.当我们希望将JDBC ResultSets中的数据,转化为合理的Java对象时,你就能感受到它的非凡之处.正如其官方所述的那样: re ...

  2. Mybatis中强大的resultMap

    本文来说下mybatis中的resultMap,在平时的开发中resultType使用的比较多.resultType在解决一对一的关系时候比较方便,但是在设计到多对多的时候,使用resultMap比较 ...

  3. resultmap的写法_Mybatis的ResultMap的使用

    本篇文章通过一个实际工作中遇到的例子开始吧: 工程使用Spring+Mybatis+Mysql开发.具体的业务逻辑很重,对象之间一层一层的嵌套.和数据库表对应的是大量的model类,而和前端交互的是V ...

  4. java resultmap_Mybatis中强大的resultMap功能介绍

    前言 在Mybatis中,有一个强大的功能元素resultMap.当我们希望将JDBC ResultSets中的数据,转化为合理的Java对象时,你就能感受到它的非凡之处.正如其官方所述的那样: re ...

  5. resultmap的写法_mybatis的mapper.xml中resultMap标签的使用详解

    1.前言 最近博主在做一个ssm框架的共享汽车管理系统,其中,数据库字段设计的有下划线方式,a_username,然后在写mapper.xml里面的sql语句的时候,一直出现查询语句查询的值为null ...

  6. batchupdate写法_Mybatis中使用updateBatch进行批量更新

    背景描述:通常如果需要一次更新多条数据有两个方式,(1)在业务代码中循环遍历逐条更新.(2)一次性更新所有数据(更准确的说是一条sql语句来更新所有数据,逐条更新的操作放到数据库端,在业务代码端展现的 ...

  7. Mybatis中强大的功能元素:resultMap

    转载自  Mybatis中强大的功能元素:resultMap 前言 在Mybatis中,有一个强大的功能元素resultMap.当我们希望将JDBC ResultSets中的数据,转化为合理的Java ...

  8. resultmap的写法_如何向resultMap中的collection中配置的select传递条件

    匿名用户 1级 2016-10-21 回答 一.概述 MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返 ...

  9. 一文理清Mybatis中resultType与resultMap之间的关系和使用场景

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 1.概述 Mybatis ORM半自动映射框架对java开发工程师来说应该是必会的框架之一. ...

最新文章

  1. Web前端之html_day2
  2. 近六成员工强烈支持,携程将推出“3+2 ”工作模式,一周三天到岗两天在家办公...
  3. 行程日志2010-03-16沙井一村(1)
  4. nodeJs 接收请求参数和发送请求参数
  5. python编程入门与案例详解-python编程入门知识练习
  6. 项目背景一般写什么_项目申报整体框架规划思路,提高你的书写逻辑!
  7. 原生js之同级元素添加移除class
  8. 海康威视摄像头web端播放
  9. Js实现继承的6种方式
  10. 编写程序,求柱体的体积:
  11. 列表,元组,字典,集合类型变量相关内置函数详解
  12. JavaWeb-文件上传和下载
  13. 用JavaScript实现烟花效果
  14. 用Python画笑脸
  15. Java——时间复杂度、空间复杂度详解
  16. PMQ - 推送项目上线一年后的总结和复盘
  17. 人工智能以及图形图像处理领域CCFA类期刊汇总与个人评价
  18. DVB Project 浅谈
  19. 三花集金花茶“茶族皇后”不仅貌美,还有丰富的营养价值
  20. 在ppt当中加背景音乐一直播放的

热门文章

  1. WinServer添加任务计划
  2. 支付宝小程序又出招!开放花呗分期
  3. matlab与工控机PCI板卡连接2020.12.10
  4. 【第47题】常用的数学工具类4-双曲函数的使用
  5. 金山词霸命令行客户端
  6. C语言 递归实现汉诺塔问题 【图文讲解、简单易懂】
  7. 祝大家新年快乐,诸事大吉!
  8. 主动学习(Active Learning,AL)的理解以及代码流程讲解
  9. Android - 最基础的控件TextView
  10. ***系列-以彼之道还施彼身