在系统开发中,一对一、一对多的数据关系很常见,可以通过关联查询也很容易实现。但随着系统业务越复杂,服务划分越小,关联查询的局限性也变得明显。
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从入门到精通》)