最近项目中使用到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<>();
}
角色类
public class Role {
private Long id;
private String name;
private String description;
private Set<Permission> permissionSet =
new HashSet<>();
}
权限类
public class Permission {
private Long id;
private String name;
private String description;
}
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);
总结
在使用一对多功能时,无论要查询的结果的主体是否唯一,返回值必须设为集合类,否则不会生效。