-
Notifications
You must be signed in to change notification settings - Fork 154
Description
确认
功能改进
当前程序版本
1.5.5(MyBatis-Plus 3.5.15,Java 25)
功能描述
希望 selectJoinList / selectJoinPage 等查询方法能支持 Java Record 类作为 resultType。
目前使用 Record 接收联表查询结果会报错,改为带 setter 的普通类就正常。
复现代码
// Record 定义
public record UserRoleRecord(Long id, String username, String nickname, Long roleId) {}
// 查询
var wrapper = new MPJLambdaWrapper()
.select(SysUser::getId, SysUser::getUsername, SysUser::getNickname)
.select(SysUserRole::getRoleId)
.leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
.last("limit 5");
// 报错
List list = userMapper.selectJoinList(UserRoleRecord.class, wrapper);
改为普通类则正常:
@DaTa
public static class UserRoleClass {
private Long id;
private String username;
private String nickname;
private Long roleId;
}
// 正常
List list = userMapper.selectJoinList(UserRoleClass.class, wrapper);
原因分析
MPJInterceptor.buildResultMap() 构建 ResultMapping 时,始终使用 property 映射(依赖 setter
赋值),没有判断目标类是否为 Record。
Record 是不可变类型,没有 setter,需要通过构造函数映射(ResultFlag.CONSTRUCTOR)来创建对象。MyBatis 本身从 3.5.10+
已支持 Record 的 constructor 映射,但 MPJ 动态构建 ResultMap 时未兼容。
建议在 buildResultMap() 中增加类似逻辑:
if (resultType.isRecord()) {
for (RecordComponent rc : resultType.getRecordComponents()) {
resultMappings.add(new ResultMapping.Builder(...)
.flags(Collections.singletonList(ResultFlag.CONSTRUCTOR))
.build());
}
}
报错日志
org.apache.ibatis.reflection.ReflectionException: Could not set property 'id' of
'class com.romeo.boot.controller.MpjRecordTestController$UserRoleRecord' with value '1'
Cause: There is no setter for property named 'id' in
'class com.romeo.boot.controller.MpjRecordTestController$UserRoleRecord'
SQL: SELECT t.id, t.username, t.nickname, t1.role_id
FROM sys_user t LEFT JOIN sys_user_role t1 ON (t1.user_id = t.id)
WHERE t.deleted=0 limit 5
参考资料
No response