我们有一个使用DTO接口投影和CrudRepository的工作仓库实现。
我想把这些DTO接口转换成DTO类,因为我们需要它们在Redis缓存中是可序列化的。接口的Spring代理没有序列化/反序列化到数据存储所需的构造函数:
2023-01-18 15:13:28.949 ERROR 39286 [undedElastic-15] Error retrieving Mono value from redis cache: {}
org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Cannot construct instance of `com.sun.proxy.$Proxy173` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
不幸的是,当Spring尝试将查询结果转换为新的DTO时,我遇到了失败,并得到了如下错误:
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:322)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ Handler com.clickbank.clientanalytics.controller.AccountSalesHealthController#grossSalesByAffiliate(JwtAuthenticationToken, AnalyticsRequest) [DispatcherHandler]
实体模型(会计销售健康):
/* Minimal table definition to use hibernate's CrudRepository */
@Data
@Entity
@Table(name = "mv_ca_account_sales_health")
public class AccountSalesHealth {
@Id
private Integer id;
}
现有存储库接口:
public interface AccountSalesHealthRepository extends CrudRepository<AccountSalesHealth, String> {
@Query(
value = "select vendor_master_account as vendorMasterAccount" +
" , vendor" +
" , affiliate" +
" , bus_date as busDate" +
" , sum(sale_amount) as amount " +
"from mv_ca_account_sales_health " +
"where vendor_master_account = :vendorMasterAccount" +
" and bus_date >= :start" +
" and bus_date <= :end " +
"group by 1, 3, 2, 4",
nativeQuery = true
)
Collection<AccountSalesHealthDto> getGrossSalesByAffiliate(@Param("vendorMasterAccount") String vendorMasterAccount, @Param("start") String start, @Param("end") String end);
...
旧的DTO类(此类有效):
public interface AccountSalesHealthDto {
String getVendorMasterAccount();
String getVendor();
String getBusDate();
String getAffiliate();
String getItemNo();
Double getAmount();
Double getAffAmount();
Double getNetAmount();
Integer getSaleCount();
}
转换为类后:
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class AccountSalesHealthDto {
private String vendorMasterAccount;
private String vendor;
private String busDate;
private String affiliate;
private String itemNo;
private Double amount;
private Double affAmount;
private Double netAmount;
private Integer saleCount;
}
有一些关于基于类的投影的注解here似乎是适用的,这一点非常重要:
对于与存储库接口协同工作的投影类,其构造函数的参数名必须与根实体类的属性匹配。
我试过几种方法,似乎都没有效果:
- 将除
Id
之外的其他属性添加到Entity类 - 重载DTO构造函数,使
Id
参数成为参数之一 - 生成构造函数,而不是使用Lombok标注指定构造函数参数的名称。
- 除上述内容外,添加第4节所述的
equals
和hashCode
。
我错过什么了吗?
1条答案
按热度按时间vaj7vani1#
您可能错过了Spring Data JPA文档中的注解,其中写道:
基于类的投影根本不适用于本地查询。作为一种解决方案,您可以使用带有
ResultSetMapping
或Hibernate特定ResultTransformer
的命名查询。按照建议,可以使用
@NamedNativeQuery
定义本机查询,使用@SqlResultSetMapping
定义本机查询结果到DTO类的Map。有关详细信息,请查看the blog post。