resultMap 用法?工作中是怎么实现“多表联查”的?
  TEZNKK3IfmPf 2024年03月30日 60 0

一、resultMap用法


1.1、使用场景

  • 字段名称和程序中的属性名不同的情况,可使⽤ resultMap 配置映射;
  • ⼀对⼀和⼀对多关系可以使⽤ resultMap 映射并查询数据(在多表查询中,resultMap 不是企业中最常用的,后面讲多表查询的时候会讲一种最常用的方法)。

Ps拓展:

当程序中的属性名和表中的字段名不一致时的解决方案有两种:

1、使用 resultMap 标签(本篇重点讲解)。

2、使用数据库中的别名 as 重命名。

1.2、用法说明

1.2.1、模拟场景

例如,我们的表是这样定义的,如下:

resultMap 用法?工作中是怎么实现“多表联查”的?但是程序中定义的熟悉如下(username字段 变成了 name属性):

resultMap 用法?工作中是怎么实现“多表联查”的?

这时候如果通过id来查询用户的全部数据,那么得到的 userinfo 对象的 name 属性值就为空,也就是说,当表中的字段名和属性名不一致时,查询到该属性的值就是空

1.2.2、使用

这时候可以使用 resultMap来映射不一样的字段名就可以解决上述问题,如下:

    <resultMap id="baseMap" type="com.example.demo.entity.Userinfo">
        <id column="id" property="id"></id>
        <result column="username" property="name"></result>
        <result column="password" property="password"></result>
        <result column="photo" property="photo"></result>
        <result column="createtime" property="createtime"></result>
        <result column="updatetime" property="updatetime"></result>
        <result column="state" property="state"></result>
    </resultMap>

    <select id="getUserById" resultMap="baseMap">
        select * from userinfo where id = ${id}
    </select>

解释:

 resultMap 用法?工作中是怎么实现“多表联查”的?

二、多表联查


2.1、分析

也许你听到过使用 association 进行多表联查,但是有些情况下显得过于繁琐,所以对于多表查询最终的一个解决方案:联合查询语句(left join / right join...) + XXXVO 来解决(这里的XXX 表示类名,VO 是 ViewObject 的缩写,这个类表示:是在一个实体类的基础上多加了一些属性值而新创建的一个类)。

例如:现在有一个文章表(articleinfo),和一个用户表(userinfo)如下,需要通过查询用户的 id 来查询该用户的所有文章,我们需要保留的字段为 文章表的所有信息 和 用户表的用户名,那么我们的 sql 可以这样写,如下(例如查询 id = 1):

select a.*, u.username from articleinfo a 
left join userinfo u 
on a.uid = u.id 
where u.id = 1;

2.2、方法一:直接copy父类属性

具体的,我们按照如下步骤进行联合查询:

a)创建一个  XXXVO  类,它的基础实体类为 文章表 ,通过上面的 sql 查询可以知道,还需要增加 用户表的用户名属性,如下代码:

@Data
public class ArticleinfoVO extends Articleinfo implements Serializable {

    private final long serializable = 1L;//用来保证兼容序列化和反序列化版本;


    //新增的属性(用户表的用户名)
    private String username;

    //以前创建的基础表具有的属性
    private int id;
    private String title;
    private String content;
    private String createtime;
    private String updatetime;
    private int uid;
    private int rcount;
    private int state;

}

Ps:

1.继承 Serializable 接口是为了防止序列化和反序列化会出问题(建议实体类都写上!防止某些特定场景报错(例如使用Redis缓存就一定会报错));

2.private final long serializable = 1L; 用来保证兼容序列化和反序列化版本,当有新版本出现时,直接修改值即可。

 

b)设计接口,传入 id 即可,如下代码:

import com.example.demo.entity.vo.ArticleinfoVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface ArticleMapper {

    ArticleinfoVO getAllVOById(@Param("id") Integer id);

}

Ps:注意返回类型是 XXXVO 类

 

c)在 XXXMapper.xml 文件中,实现对应 sql 即可,如下代码:

    <select id="getAllVOById" resultType="com.example.demo.entity.vo.ArticleinfoVO">
        select a.*, u.username from articleinfo a
        left join userinfo u on a.uid = u.id
        where a.id = #{id}
    </select>

2.3、方法二:继承父类属性

和方法一的步骤一样,唯一需要我们进行修改的就是 XXXVO 类这里我们使用一个继承的方式,如下:

import com.example.demo.entity.Articleinfo;
import lombok.Data;

@Data
public class ArticleinfoVO extends Articleinfo implements Serializable {

    private final long serializable = 1L;//用来保证兼容序列化和反序列化版本;


    //新增的属性(用户表的用户名)
    private String username;

    //这里由于 lombok 的原因( lombok 的 toString 方法不会描述父类的属性),
    @Override
    public String toString() {
        return "ArticleinfoVO{" +
                "username='" + username + '\'' +
                "} " + super.toString();
    }
}

值得注意的是:我们需要重写 toString 方法,因为 lombok 的 toString 方法不会描述父类的属性!

2.4、总结

这样就可以实现一个更简单的联合查询啦~ 这种方式具有更高的灵活性,如果联合查询结果需要更多的属性时,那么只需要重新创建一个类,赋值旧的实体类,增加新的属性值即可~

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2024年03月30日 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   21天前   47   0   0 java
  TEZNKK3IfmPf   2024年05月31日   31   0   0 数据库mysql
TEZNKK3IfmPf