如何解决如何在Spring JPA存储库中将SQL本机查询结果映射到DTO?
您好,我想实现的是将sql本机查询结果映射映射到java spring jpa存储库中的DTO中,如何正确执行此操作?我尝试了几种代码,但没有用,这是我尝试过的:
第一次尝试:
@Repository
public interface StockRepository extends RevisionRepository<Stock,Long,Integer>,JpaRepository<Stock,Long> {
@Query(value = "SELECT stock_akhir.product_id AS productId,stock_akhir.product_code AS productCode,SUM(stock_akhir.qty) as stockAkhir "
+ "FROM book_stock stock_akhir "
+ "where warehouse_code = (:warehouseCode) "
+ "AND product_code IN (:productCodes) "
+ "GROUP BY product_id,product_code,warehouse_id,warehouse_code",nativeQuery = true)
List<StockAkhirDto> findStockAkhirPerProductIn(@Param("warehouseCode") String warehouseCode,@Param("productCodes") Set<String> productCode);
}
未找到能够从类型转换的转换器 [org.springframework.data.jpa.repository.query.AbstractJpaQuery $ TupleConverter $ TupleBackedMap] 键入[com.b2bwarehouse.Dto.RequestDto.StockDto.StockAkhirDto]
第二次尝试:
@Repository
public interface StockRepository extends RevisionRepository<Stock,Long> {
@Query(value = "SELECT new com.b2bwarehouse.Dto.RequestDto.StockDto.StockAkhirDto(stock_akhir.product_id AS productId,SUM(stock_akhir.qty) as stockAkhir) "
+ "FROM book_stock stock_akhir "
+ "where warehouse_code = (:warehouseCode) "
+ "AND product_code IN (:productCodes) "
+ "GROUP BY product_id,@Param("productCodes") Set<String> productCode);
}
第二秒钟出现错误:
无法提取ResultSet; sql [n / a];嵌套异常为 org.hibernate.exception.sqlGrammarException:无法提取 结果集
以下是我的DTO:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StockAkhirDto {
private Long productId;
private String productCode;
private Integer stockAkhir;
}
我应该如何更正我的代码?那么,我可以将结果存入DTO吗?
解决方法
您可以使用适当的sql结果集映射定义以下命名的本机查询:
import javax.persistence.NamedNativeQuery;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.ConstructorResult;
import javax.persistence.ColumnResult;
@Entity
@NamedNativeQuery(
name = "find_stock_akhir_dto",query =
"SELECT " +
" stock_akhir.product_id AS productId," +
" stock_akhir.product_code AS productCode," +
" SUM(stock_akhir.qty) as stockAkhir " +
"FROM book_stock stock_akhir " +
"where warehouse_code = :warehouseCode " +
" AND product_code IN :productCodes " +
"GROUP BY product_id,product_code,warehouse_id,warehouse_code",resultSetMapping = "stock_akhir_dto"
)
@SqlResultSetMapping(
name = "stock_akhir_dto",classes = @ConstructorResult(
targetClass = StockAkhirDto.class,columns = {
@ColumnResult(name = "productId",type = Long.class),@ColumnResult(name = "productCode",type = String.class),@ColumnResult(name = "stockAkhir",type = Integer.class)
}
)
)
public class SomeEntity
{
}
然后使用它:
@Repository
public interface StockRepository extends RevisionRepository<Stock,Long,Integer>,JpaRepository<Stock,Long> {
@Query(name = "find_stock_akhir_dto",nativeQuery = true)
List<StockAkhirDto> findStockAkhirPerProductIn(
@Param("warehouseCode") String warehouseCode,@Param("productCodes") Set<String> productCode
);
}
,
第二个变体非常接近。您只需要删除构造函数表达式的别名:
new com.b2bwarehouse.Dto.RequestDto.StockDto.StockAkhirDto(
stock_akhir.product_id,stock_akhir.product_code,SUM(stock_akhir.qty)
)
应该工作。
,我找到了一种不常见的方法,但是当我尝试使用QueryDsl解决此问题时,我发现了称为“元组” 的数据类型,但是如果您只是一个人,我就不建议使用QueryDsl像我一样开始。让我们专注于我如何使用“元组”
我将返回类型更改为元组,这是我的存储库的外观:
@Repository
public interface StockRepository extends RevisionRepository<Stock,Long> {
@Query(value = "SELECT stock_akhir.product_id AS productId,stock_akhir.product_code AS productCode,SUM(stock_akhir.qty) as stockAkhir "
+ "FROM book_stock stock_akhir "
+ "where warehouse_code = (:warehouseCode) "
+ "AND product_code IN (:productCodes) "
+ "GROUP BY product_id,nativeQuery = true)
List<Tuple> findStockAkhirPerProductIn(@Param("warehouseCode") String warehouseCode,@Param("productCodes") Set<String> productCode);
}
然后在我的服务类中,由于它以Tuple的形式返回,因此我必须手动一一映射该列,这是我的服务函数:
public List<StockTotalResponseDto> findStocktotal() {
List<Tuple> stockTotalTuples = stockRepository.findStocktotal();
List<StockTotalResponseDto> stockTotalDto = stockTotalTuples.stream()
.map(t -> new StockTotalResponseDto(
t.get(0,String.class),t.get(1,t.get(2,BigInteger.class)
))
.collect(Collectors.toList());
return stockTotalDto;
}
列字段以0开头,这样我就可以在存储库级别保持查询整洁。但是我会接受SternK答案作为接受的答案,因为那样也行得通,如果有人需要这样的东西,我会将答案保留在这里
,创建标准的原生@Query
@Query(value = "select id,age,name FROM Person WHERE age=?1",nativeQuery=true)
List<PersonView> getPersonsByAge(int age);
和一个界面
public interface PersonView {
Long getId();
Integer getAge();
String getName();
}
列按顺序匹配(而不是按名称)。 这样,您就有了一个原生查询,没有实体,也没有太多的样板代码(也就是很多注释)。
但是,结果视图(Jdk 代理等)的访问速度非常慢,我有一些代码对流进行了一些分组,结果是 10 倍!!比标准 DTO/Pojos 慢! 所以最后,我不再使用 nativeQuery,但是:
SELECT new com.my_project.myDTO(p.id,p.age,p.name) .....
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。