Mybatis通过ResultMap实现关联查询

Mybatis通过ResultMap实现关联查询

本文主要讲通过以resultmap为主实现mybatis一对一、一对多的关联查询的两种方式。

实体类关系

用户类(User)与用户组别类(Group),关系为一对一。
用户类(User)与邮件类(Mail),关系为一对多。
即每个用户有一个自己归属的组别,同时这个用户手里也有多条接收到的邮件。

User{
    private Long userId;
    private String userName;
    private String userPass;
    private Long groupId;
}
Group{
    private Long groupId;
    private String groupName;
}
Mail{
    private Long mailId;    
    private Long userId;    //邮件通过userId来进行关联查询
    private String recipient;
    private String sender;
    private String detail;
}

1、通过join进行sql的连接查询

首先写对应的select查询语句,以左连接的方式查询出对应的Group信息和Mail信息

    <select id="selectUserWithAll" resultMap="UserWithAll">
        select u.*,g.*,m.* from User u
        left join Group g on g.groupId = u.groupId
        left join Mail m on m.user = u.userId
        where u.userId = #{userId}
    </select>

于是在执行该方法时,mybatis会依照该sql语句查询出对应的用户的用户信息、组别信息和邮件信息,并将该信息存入UserWithAll这个resultMap指向的实体类。为了接收这些信息,需要新建一个实体类UserWithAll,内容如下

UserWithAll extends User{
    private Group group;
    private List<Mail> mail;
}

在有了对应的储存位置后,配置resultMap的映射关系,其映射关系为将select查询结果映射至UserWithAll这个实体类中,具体如下。

<resultMap id="UserWtihAll" type="com.test.model.entity.UserWithAll">
        <id property="userId" column="user_id"/>
        <result property="userName" column="user_name"/>
        <result property="userPass" column="user_pass"/>
        <result property="groupID" column="group_id"/>
        <association property="group" javaType="com.test.model.entity.Group"
        resultMap="com.test.repository.mybatis.UserMapper.Group"/>
        <collection property="mail" javaType="com.test.model.entity.Mail"
        resultMap="com.test.repository.mybatis.UserMapper.Mail"/>
</resultMap>

在上面的配置中,association和collection分别对应一对一查询和一对多查询,这两个对应新的resultMap来实现相应的映射,要注意的是association不能接收多条数据,否则会报错。下面分别对这两个来写映射关系。

<resultMap id="group" type="com.test.model.entity.Group">
        <id property="groupId" column="group_id"/>
        <result property="groupName" column="group_name"/>
</resultMap>
<resultMap id="mail" type="com.test.model.entity.Mail">
        <id property="userId" column="user_id"/>
        <result property="mailId" column="mail_id"/>
        <result property="recipient" column="recipient"/>
        <result property="sender" column="sender"/>
        <result property="detail" column="detail"/>
</resultMap>

在完成以上内容后,在DAO层用List<UserWithAll> selectUserWithAll()方法即可获取到对应的关联查询结果。

2、通过嵌套的select查询实现关联查询

该方法相比其连接查询而言效率更高,同时由于可以自定义select查询,比起连接查询也要更灵活一些。首先依旧是先配置UserWithAll的resultMap,区别在于<association/><collection/>这两个标签,需要配置这两个要执行的select方法以及传入的参数名,具体如下。

<resultMap id="UserWtihAll" type="com.test.model.entity.UserWithAll">
        <id property="userId" column="user_id"/>
        <result property="userName" column="user_name"/>
        <result property="userPass" column="user_pass"/>
        <result property="groupID" column="group_id"/>
        <association property="group" column="group_id"
        select="com.test.repository.mybatis.UserMapper.selectGroupById"/>
        <collection property="mail" column="user_id"
        select="com.test.repository.mybatis.UserMapper.selectMailByUserId"/>
</resultMap>

这里<association/>中的property指的是返回到UserWithAll时对应的属性,column指的是将数据库中哪个字段传入该select方法,select指的是调用哪里的select方法,这里select的路径也可以改为其他Mapper文件里的select方法,比如说是你的参数表映射文件ParamMapper,那么这里的为select="com.test.repository.mybatis.ParamMapper.selectMailByUserId。在完成这部分后在写对应的select方法及对应的resultMap,如

<resultMap id="group" type="com.test.model.entity.Group">
        <id property="groupId" column="group_id"/>
        <result property="groupName" column="group_name"/>
</resultMap>
<select id="selectGroupById" resultMap="Group">
    select * from Group where group_id=#{group_id}
</select>

同样的Mail的resultMap与select也跟这个一样,不再赘述。经过以上配置后,在执行相应的如List<UserWithAll> selectUserWithAll()这样的方法时,会自动执行Group与Mail的select方法,然后通过resultMap映射至UserWithAll实体类中的group与mail中。

3、总结

这两种方法都可以实现表关联查询,区别在于一种关联查询是通过数据库的sql语句直接获取相应的信息,另一种则是通过resultMap先执行关联的查询,将结果映射回本身的resultMap。两者比较起来的话,前者书写简单,只要配一个resultMap以及在select里加上left join一类的关键字就可以,但执行效率不高,特别是在没有给外键建立索引且数据量较大的情况下,这种方法耗费时长可以说是令人发指。后者书写要稍微麻烦一点,一个是除了要配置resultMap外,还要单独写一份sql语句,但是效率要远高于前者。所以如果是小量数据的关联查询用left join无可厚非,如果数据量大的话尽量使用后者这种方式。顺带一提这两个方式也是可以结合使用的,比如A、B、C三张表关联查询,其中AB数据量较大,C只是A表的一张参数表,那么可以给A和B使用后者那种方法,以A为基础建立resultMap,加入<association property="B" column="A.id" select="selectB"/>或者<collection property="B" column="A.id" select="selectB"/>进行关联的查询,然后在这个resultMap里加一个<association property="C" javaType="xx.xx.C" resultMap="xx.xx.C"/>指向C的resultMap,在查询语句里left join C表即可。

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
resultMapMyBatis 用于自定义查询结果的映射方式。通过 resultMap,我们可以定义字段名和属性名的对应关系,并且可以选择性地指定要显示的列,使结果映射更加灵活和方便。使用 resultMap 可以实现字段名与属性名不一致的映射,以及关联查询时的结果处理。 需要注意的是,resultType 和 resultMap 在 select 元素是互斥的,即不能同时存在,只能选择其一个来定义返回类型。resultType 直接表示返回的类型,而 resultMap 则是对外部 resultMap 的引用。 使用 resultMap 的场景多种多样,可以根据实际需求灵活选择。推荐使用 resultMap,因为它更加灵活,并且在自定义结果映射方面功能更强大。 总结来说,resultMapMyBatis 用于自定义查询结果的映射方式,可以实现字段名与属性名的对应关系,并且可以选择性地指定要显示的列,使结果映射更加灵活和方便。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [MyBatisresultMap详解](https://blog.csdn.net/weixin_49707895/article/details/109564527)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值