MyBatis(七)一对一查询结果映射

在系统开发中,一对一、一对多的数据关系很常见,可以通过关联查询也很容易实现。但随着系统业务越复杂,服务划分越小,关联查询的局限性也变得明显。

MyBatis提供了高级结果映射来处理这种一对一、一对多的关系。

 

假设在权限设计中,用户和角色是一对一的关系。

首先,在SysUser实体类中添加角色对象role,并在UserMapper.xml中添加resultMap:

    /**
     * 角色
     */
    private SysRole role;

    public SysRole getRole() {
        return role;
    }

    public void setRole(SysRole role) {
        this.role = role;
    }
    <resultMap id="userRoleMapSelect" type="tk.mybatis.simple.model.SysUser" extends="userMap">
        <association property="role" column="role_id"
                     javaType="tk.mybatis.simple.model.SysRole"
                     select="tk.mybatis.simple.mapper.RoleMapper.selectById" fetchType="lazy"/>
    resultMap>

接下来,分别在UserMapper接口类和UserMapper.xml中添加方法:

    /**
     * 根据用户id获取用户信息和用户的角色信息(嵌套查询)
     * @param id
     * @return
     */
    SysUser selectUserByRoleIdSelect(Long id);
    <select id="selectUserByRoleIdSelect" resultMap="userRoleMapSelect">
        select u.id, u.user_name, u.user_password, u.user_email, u.user_info, u.head_img, u.create_time, ur.role_id
        from sys_user u
        inner join sys_user_role ur on u.id = ur.user_id
        where u.id = #{id}
    select>

然后,添加测试方法运行查询:

    @Test
    public void testSelectUserAndRoleBySelect() {
        SqlSession sqlSession = getSqlSession();
        try {
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            SysUser user = userMapper.selectUserByRoleIdSelect(1001L);
            Assert.assertNotNull(user);
            Assert.assertNotNull(user.getRole());
        } finally {
            sqlSession.close();
        }
    }

 

通过控制台输出可知,在上面的查询中,已经不通过直接的关联查询来直接查询所有的信息,而是分两步查询,先通过查询出关联的角色ID,再通过角色ID嵌套查询用户信息,最后将获得的查询结果映射到用户对应的角色对象。

association标签属性如下:

  • property:对应实体类中的属性名,必填项。
  • javaType:属性对应的Java类型。
  • resultMap:可以直接使用现有的resultMap,而不需要在这里配置。
  • columnPrefix:查询列的前缀,配置前缀后,在子标签配置result的column时可以省略前缀。
  • select:另一个映射查询的id,MyBatis会额外执行这个查询获取嵌套对象的结果。
  • column:列名(或别名),将主查询中列的结果作为嵌套查询的参数,如果有多个参数,可按照column="{prop1=col1,prop2=col2,...}"的方式配置。
  • fetch:数据加载方式,将主查询可选值为lazy和eager,分别为延迟加载和积极加载,这个配置会覆盖全局的lazyLoadingEnabled配置。

 

在实际使用过程中,可能会遇到在延迟加载时报错的情况。

MyBatis延迟加载是通过动态代理实现的,当调用配置为SqlSession去执行嵌套SQL时,动态代理的操作会被触发,这些额外的操作就是通过MyBatis的SqlSession去执行嵌套SQL的。在和Spring集成时,要确保只能在Service层调用延迟加载属性。当结果从Service层返回至Controller层时,如果获取延迟加载的属性值时,会因为SqlSession已经关闭而抛出异常。

 

(以上内容整理自《MyBatis从入门到精通》)

你可能感兴趣的:(MyBatis(七)一对一查询结果映射)