Day14.高级查询 一对一映射关系 -MyBatis高级

1. 高级查询简介

在实际开发过程中,常常要处理关系型数据库中一对一 一对多的情景,例如:

  • 一个汽车有一个引擎(一对一)
  • 一个汽车有四个轮子(一对多)

RABC系统中还存在一个用户对应多个角色,一个角色有多种权限这样复杂的嵌套关系。

这个时候我们就需要写多个查询方法,然后组合在一起。这样做不仅仅能减少表之间的关联,还使得系统的可拓展性大大提高。

2. 一对一映射

创建数据

假设一个用户只有一种角色,即用户于角色是一对一的关系

@Data
@AllArgsConstructor
@NoArgsConstructor
//用户实体类
public class User {
    private Integer id;
    private String username;
    private String password;
    private Role role;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
//角色类
public class Role {
    private Integer id;
    private String role;
    private Date createDate;
}

2.1 关联的嵌套结果映射

2.1.1 使用自动映射处理一对一关系

使用自动映射就是让MyBatis将值自动匹配到对应的字段上。例如:

  • user_name匹配到userName
  • role.role_name匹配到role.roleName(这属于复杂嵌套,MyBatis会先查找role属性,如果存在role属性就创建role对象,然后再从对象中查找roleName属性,最后将role_name的值绑定到上面)

UserMapper.xml中的方法:

    <select id="selectUserAndRoleById" resultType="com.example.pojo.User">
        select user.id, username, password, r.id "role.id", r.role "role.role", r.create_date "role.createDate"
        from user
                 inner join user_role_merage urm on user.id = urm.user_id
                 inner join role r on urm.role_id = r.id
        where user.id = #{id}
    </select>

注意:上面role表的查询的列的名都有"role."前缀,通过这种方式可以将值绑定到user中的role属性上
在这里插入图片描述
测试成功
在这里插入图片描述

  • 像这种通过一次查询将结果映射到不同对象的方式,称之为关联的嵌套结果查询。
  • 关联的嵌套结果查询需要关联多张表一次性将所需要的数据全部查询出来
  • 关联的嵌套结果的查询的好处是:减少数据库查询次数,减轻数据库压力;缺点是:需要写出比较复杂的SQL

2.1.2 使用resultMap配置一对一映射

使用resultMap配置可以实现与2.1 使用自动映射处理一对一关系相同的结果。

    <resultMap id="userRoleMap" type="com.example.pojo.User">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="role.id" column="role_id"/>
        <result property="role.role" column="role_role"/>
        <result property="role.createDate" column="role_create_date"/>

    </resultMap>

    <select id="selectUserAndRoleById" resultMap="userRoleMap">
        select user.id, username, password, r.id "role_id", r.role "role_role", r.create_date "role_create_date"
        from user
                 inner join user_role_merage urm on user.id = urm.user_id
                 inner join role r on urm.role_id = r.id
        where user.id = #{id}
    </select>

使用resultMap这种配置与自动映射完成一对一关系中相似的地方是:property配置部分都使用了role.前缀
测试成功:
在这里插入图片描述
与上一种方法相比,resultMap的方法非常繁琐,甚至增加了更多的工作量。MyBatis是支持resultMap继承的,因此要简化上面的写法。

    <resultMap id="userMap" type="com.example.pojo.User">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
    </resultMap>
    
    <!--userRoleMap只需要继承userMap并且添加role特有的配置即可-->
    <resultMap id="userRoleMap" extends="userMap" type="com.example.pojo.User">
        <result property="role.id" column="role_id"/>
        <result property="role.role" column="role_role"/>
        <result property="role.createDate" column="role_create_date"/>
    </resultMap>

使用简化后的resultMap配置一对一映射仍然不算方便,至少没有那么麻烦

2.1.3 使用resultMap的association标签配置一对一映射

association标签用于和一个复杂类型相关联,即用于一对一的关联配置。
对上面的代码进行修改:

    <resultMap id="userRoleMap" extends="userMap" type="com.example.pojo.User">
       <association property="role" javaType="com.example.pojo.Role"
                    columnPrefix="role_">
           <result property="id" column="id"/>
           <result property="role" column="role"/>
           <result property="createDate" column="create_date"/>
       </association>
    </resultMap>
  • association中配置了role,所以在result中的property中就按属性名写;
  • columnPrefix设置了字段前缀,MyBatis会根据字段前缀+column去匹配查询出的字段

使用association配置时还可以使用resultMap属性来配置一个现成的resultMap映射。

    <resultMap id="userRoleMap" extends="userMap" type="com.example.pojo.User">
        <association property="role" javaType="com.example.pojo.Role"
                     columnPrefix="role_" resultMap="com.example.mapper.RoleMapper.roleMapper">
        </association>
    </resultMap>

RoleMapper.xml

    <resultMap id="roleMapper" type="com.example.pojo.Role">
        <id property="id" column="id"/>
        <result property="role" column="role"/>
        <result property="createDate" column="create_date"/>
    </resultMap>

这种方法是比较简单的,原因之一就是MyBatis可以自动生成resultMap

以上的三种方法都属于“关联的嵌套结果映射”,意思就是通过一次查询将不同的属性值映射到不同的对象中。还有一种:关联的嵌套查询,言外之意就是有额外的查询。

2.2 关联的嵌套查询

2.2.1 association标签的嵌套查询

除了使用关联的嵌套结果映射,我们还可以利用简单的SQL通过多次查询来获得我们的结果,这种方法和在逻辑层手动执行多次SQL的方式很像,最后会将结果组合成一个对象
association嵌套查询常用的属性如下:

  • select:另一个映射查询的id,MyBatis会额外执行这个查询获取嵌套对象的结果。
  • column:将主查询中列的结果作为嵌套查询的参数,配置方式:column={prop1=col1,prop2=col2},其中,prop1和prop2为参数。
  • fetchType:加载方式:lazy或者eager

代码如下:

    <resultMap id="userRoleMap" extends="userMap" type="com.example.pojo.User">
        <association property="role" select="com.example.mapper.RoleMapper.selectRoleById" column="{id=role_id}"/>
    </resultMap>
    <select id="selectUserAndRoleById" resultMap="userRoleMap">
        select user.id, username, password ,urm.role_id
        from user
                 inner join user_role_merage urm on user.id = urm.user_id
        where user.id = #{id}
    </select>

RoleMapp.xml

    <select id="selectRoleById" resultType="com.example.pojo.Role">
        select * from role where id = #{id}
    </select>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值