最近项目中使用到mybatis的一对多的功能,需求是查找特定用户对应的所有角色和权限
涉及的实体类
用户类
public class User {
private Long id;
private String userId;
private String name;
private String mobile;
private String role;
private Set<Role> roleSet = new HashSet<>();
//ommitted getter/setter
}
角色类
public class Role {
private Long id;
private String name;
private String description;
private Set<Permission> permissionSet = new HashSet<>();
//ommitted getter/setter
}
权限类
public class Permission {
private Long id;
private String name;
private String description;
//ommitted getter/setter
}
mapper文件配置
<resultMap id="ResultMapWithRolePerms" type="user" >
<id column="id" property="id" jdbcType="BIGINT" />
<result column="user_id" property="userId" jdbcType="VARCHAR" />
<result column="name" property="name" jdbcType="VARCHAR" />
<collection property="roleSet" ofType="role">
<id property="id" column="role_id"/>
<result property="name" column="role_name"/>
<collection property="permissionSet" ofType="permission">
<id property="id" column="perm_id"/>
<result property="name" column="perm_name"/>
</collection>
</collection>
</resultMap>
<select id="findUserById" parameterType="string" resultMap="ResultMapWithRolePerms">
SELECT
u.user_id user_id,
u.name name,
u.mobile mobile,
r.id role_id,
r.name role_name,
p.id perm_id,
p.name perm_name
FROM
user AS u
LEFT JOIN
user_role AS ur ON (u.user_id = ur.user_id)
LEFT JOIN
role AS r ON (r.id = ur.role_id)
LEFT JOIN
role_perm AS rp ON (r.id = rp.role_id)
LEFT JOIN
permission AS p ON (p.id = rp.perm_id)
WHERE
u.user_id = #{userId};
</select>
mapper查询方法
User findUserById(String userId);
运行结果
严重: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3] with root cause
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:81)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:434)
at com.sun.proxy.$Proxy57.selectOne(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:167)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:75)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:53)
参考源码分析后,发现方法的返回值需要为List,即改为如下
List<User> findUserById(String userId);
总结
在使用一对多功能时,无论要查询的结果的主体是否唯一,返回值必须设为集合类,否则不会生效。