Ke *_*Vin 7 java spring hibernate jpa spring-data-jpa
嗨,我想要实现的是在 java spring jpa 存储库中将 SQL 本机查询结果映射到我的 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);
}
Run Code Online (Sandbox Code Playgroud)
执行该函数后,出现此错误:
没有找到能够从类型 [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] 转换为类型 [com.b2bwarehouse.Dto.RequestDto.StockDto.StockAkhirDto] 的转换器
第二次尝试:
@Repository
public interface StockRepository extends RevisionRepository<Stock, Long, Integer>, JpaRepository<Stock, Long> {
@Query(value = "SELECT new com.b2bwarehouse.Dto.RequestDto.StockDto.StockAkhirDto(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);
}
Run Code Online (Sandbox Code Playgroud)
第二个是错误:
无法提取结果集;SQL [不适用];嵌套异常是 org.hibernate.exception.SQLGrammarException: 无法提取 ResultSet
下面是我的 DTO:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StockAkhirDto {
private Long productId;
private String productCode;
private Integer stockAkhir;
}
Run Code Online (Sandbox Code Playgroud)
我应该如何更正我的代码?那么,我可以将结果输入到我的 DTO 中吗?
Ke *_*Vin 33
我找到了一种不常见的方法,但是当我尝试使用 QueryDsl 来解决这个问题时,我发现了名为“Tuple”的数据类型,但如果您像我一样刚刚开始,我不会推荐 QueryDsl。让我们重点关注我如何使用“Tuple”做到这一点
我将返回类型更改为Tuple,这是我的存储库的样子:
@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<Tuple> findStockAkhirPerProductIn(@Param("warehouseCode") String warehouseCode, @Param("productCodes") Set<String> productCode);
}
Run Code Online (Sandbox Code Playgroud)
然后在我的服务类中,由于它作为元组返回,我必须手动一一映射列,这是我的服务函数,如下所示:
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, String.class),
t.get(2, BigInteger.class)
))
.collect(Collectors.toList());
return stockTotalDto;
}
Run Code Online (Sandbox Code Playgroud)
列字段以 0 开头,这样我就可以在存储库级别保持查询整洁。但我会接受 SternK 答案作为已接受的答案,因为这种方式也有效,如果有人需要这样的东西,我会在这里保留我的答案
raz*_*zor 20
创建标准原生@Query
@Query(value = "select id, age, name FROM Person WHERE age=?1", nativeQuery=true)
List<PersonView> getPersonsByAge(int age);
Run Code Online (Sandbox Code Playgroud)
和一个接口
public interface PersonView {
Long getId();
Integer getAge();
String getName();
}
Run Code Online (Sandbox Code Playgroud)
列按顺序(而不是名称)匹配。通过这种方式,您将拥有一个本机查询,没有实体,也没有太多的样板代码(也称为许多注释)。
然而,生成的视图(Jdk 代理等)的访问速度非常慢,我有一些代码对流进行了一些分组,它是 10 倍!比标准 DTO/Pojos 慢!所以最后我不再使用nativeQuery,而是使用JPQL:
SELECT new com.my_project.myDTO(p.id, p.age, p.name) .....
Run Code Online (Sandbox Code Playgroud)
Ste*_*rnK 12
您可以使用适当的 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
{
}
Run Code Online (Sandbox Code Playgroud)
然后使用它:
@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
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9242 次 |
| 最近记录: |