能否复用同一SqlResultSetMapping映射不同原生查询结果至同一POJO?
解决JPA复用SqlResultSetMapping处理不同列组合原生查询的问题
你的问题核心在于当前使用的@ConstructorResult要求查询返回所有定义的列——它是通过匹配构造函数参数来实例化POJO的,当查询缺少某列时,JPA找不到对应的构造函数(比如查询返回a和b,但你的映射只定义了三参数构造),自然会抛出异常。
下面提供两种解决方案,推荐第一种更灵活的方式:
方案1:改用@FieldResult(推荐)
这种方式让JPA直接通过反射给POJO的字段赋值,缺少的列会自动设为null,不需要匹配构造函数,完美支持复用同一个映射处理任意列组合。
修改SqlResultSetMapping
@SqlResultSetMapping( name="GeneralResult", classes = { @EntityResult( entityClass = Result.class, fields = { @FieldResult(name="a", column="a"), @FieldResult(name="b", column="b"), @FieldResult(name="c", column="c") } ) } )
调整Result类
确保JPA能访问到类的字段,最简单的方式是添加@Access(AccessType.FIELD)注解(不需要额外写setter方法):
import javax.persistence.Access; import javax.persistence.AccessType; @Access(AccessType.FIELD) public class Result { String a; String b; String c; }
这样不管你的查询返回a+b+c、a+b还是b+c,JPA都会把存在的列赋值给对应字段,不存在的字段设为null,完全复用同一个GeneralResult映射。
方案2:添加多构造函数匹配(繁琐但可用)
如果坚持要用ConstructorResult,可以给Result类添加多个对应不同列组合的构造函数,然后在映射中定义多个ConstructorResult:
修改Result类
添加对应列组合的构造函数:
public class Result { String a; String b; String c; // 对应a+b+c的查询 public Result(String a, String b, String c) { this.a = a; this.b = b; this.c = c; } // 对应a+b的查询 public Result(String a, String b) { this.a = a; this.b = b; } // 对应b+c的查询 public Result(String b, String c) { this.b = b; this.c = c; } }
修改SqlResultSetMapping
添加多个ConstructorResult分别匹配不同构造函数:
@SqlResultSetMapping( name="GeneralResult", classes = { @ConstructorResult( targetClass = Result.class, columns = { @ColumnResult(name="a", type=String.class), @ColumnResult(name="b", type=String.class), @ColumnResult(name="c", type=String.class) } ), @ConstructorResult( targetClass = Result.class, columns = { @ColumnResult(name="a", type=String.class), @ColumnResult(name="b", type=String.class) } ), @ConstructorResult( targetClass = Result.class, columns = { @ColumnResult(name="b", type=String.class), @ColumnResult(name="c", type=String.class) } ) } )
不过这种方法的缺点很明显:每次新增列组合的查询,都要添加新的构造函数和ConstructorResult,扩展性很差,只适合列组合固定的场景。
内容的提问来源于stack exchange,提问作者Francisco Prado
相关产品推荐
相关产品推荐

