Spring Data JPA原生查询结果无法映射到DTO的解决咨询
解决方案
针对Spring Data JPA 2.1.7.RELEASE版本,原生查询结果映射到DTO可通过以下几种方式实现:
方法1:使用接口投影(最简单的只读场景方案)
创建一个与查询返回字段匹配的投影接口,Spring Data会自动实现该接口并映射结果:
public interface Xcain21Projection { int getPackageId(); String getPackageName(); }
修改Repository方法的返回类型:
@Query(value = "SELECT p.package_id, p.package_name FROM packages p WHERE p.account_id=:accountId AND (CASE WHEN :packageId IS NULL THEN TRUE " + "WHEN p.package_id LIKE :packageId THEN TRUE ELSE FALSE END) limit :offset, :limit", nativeQuery = true) List<Xcain21Projection> getPackageByAccountIdAndPackageId(String accountId, String packageId, int offset, int limit);
方法2:通过@SqlResultSetMapping+构造函数映射(适配不可变DTO)
由于你的DTO使用@Value注解生成了全参构造函数,可通过配置结果集映射实现自动转换:
- 在关联的实体类(如
Package实体)上添加映射配置:
@Entity @SqlResultSetMapping( name = "Xcain21Mapping", classes = @ConstructorResult( targetClass = com.exp.reports.traireport.dtos.Xcain21.class, // 注意使用DTO的全路径 columns = { @ColumnResult(name = "package_id", type = Integer.class), @ColumnResult(name = "package_name", type = String.class) } ) ) public class Package { // 实体类原有字段和注解 }
- 修改Repository的@Query注解,指定resultSetMapping:
@Query(value = "SELECT p.package_id, p.package_name FROM packages p WHERE p.account_id=:accountId AND (CASE WHEN :packageId IS NULL THEN TRUE " + "WHEN p.package_id LIKE :packageId THEN TRUE ELSE FALSE END) limit :offset, :limit", nativeQuery = true, resultSetMapping = "Xcain21Mapping") List<Xcain21> getPackageByAccountIdAndPackageId(String accountId, String packageId, int offset, int limit);
方法3:手动转换(最灵活的方案)
将Repository方法返回类型改为List<Object[]>,在业务层手动映射为DTO:
- 修改Repository方法:
@Query(value = "SELECT p.package_id, p.package_name FROM packages p WHERE p.account_id=:accountId AND (CASE WHEN :packageId IS NULL THEN TRUE " + "WHEN p.package_id LIKE :packageId THEN TRUE ELSE FALSE END) limit :offset, :limit", nativeQuery = true) List<Object[]> getPackageByAccountIdAndPackageId(String accountId, String packageId, int offset, int limit);
- 在Service层转换:
List<Xcain21> dtoList = repository.getPackageByAccountIdAndPackageId(accountId, packageId, offset, limit) .stream() .map(row -> new Xcain21((Integer) row[0], (String) row[1])) .collect(Collectors.toList());
注意事项
- 检查DTO的全类名是否一致:错误提示中DTO路径为
com.abc.reports.zyx.dtos.Xcain21,但你的DTO代码路径是com.exp.reports.traireport.dtos.Xcain21,需确保配置中使用的路径与实际类路径一致。 - 原生查询返回的字段名需与映射配置中的
name属性完全匹配(如package_id对应@ColumnResult(name = "package_id"))。
内容的提问来源于stack exchange,提问作者samshers
相关产品推荐
相关产品推荐

