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表即可。

MyBatisResultMap是一个非常强大的功能,它允许开发者自定义SQL查询结果映射到Java对象的过程。ResultMap可以指定如何映射结果集的列到指定的Java对象的属性,这对于处理复杂的关系(如一对多、多对一等)尤其有用。关联查询通常用于查询结果集需要根据外键关联其他表的情况,MyBatis通过ResultMap提供了多种关联查询的方式,例如: 1. association:用于处理一对一关联关系,它可以将结果集的一个字段映射到另一个对象的实例。 2. collection:用于处理一对多关联关系,它可以将结果集的一个字段映射到对象的集合属性。 使用ResultMap进行关联查询的基本步骤包括: - 在MyBatis的配置文件定义ResultMap。 - 在resultMap配置association或collection元素以表示关联关系。 - 在映射的SQL语句指定使用ResultMap。 下面是一个简单的例子: ```xml <!-- 定义一个ResultMap --> <resultMap id="userOrderMap" type="User"> <id property="id" column="user_id" /> <result property="name" column="user_name" /> <!-- 一对一关联 --> <association property="order" javaType="Order"> <id property="id" column="order_id" /> <result property="orderDate" column="order_date" /> </association> </resultMap> <!-- 映射查询 --> <select id="findUserAndOrder" resultMap="userOrderMap"> SELECT u.*, o.* FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE u.id = #{userId} </select> ``` 在这个例子,我们定义了一个名为`userOrderMap`的ResultMap,它映射了User对象和Order对象。`findUserAndOrder`查询返回的结果集会自动根据ResultMap映射到User对象,其User对象包含了一个Order类型的属性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值