我有一个DTO,如下所示:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import reactor.core.publisher.Flux;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class InternetPackageDto {
private String id;
private String name;
private String termsAndConditions;
private String price;
private Flux<String> packageAttributes;
private Flux<String> extras;
}
和一个数据库对象如下:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import reactor.core.publisher.Flux;
@Document("internet_packages")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class InternetPackage {
@Id
private String id;
private String name;
private String termsAndConditions;
private String price;
private Flux<StoreableAttribute> attributes;
private Flux<StoreableAttribute> extras;
}
StorableAttribute数据库模型如下:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document("package_attributes")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class StoreableAttribute {
@Id
private String id;
private String name;
private String description;
}
在数据对象上,字段Flux<StoreableAttribute> attributes
和Flux<StoreableAttribute> extras
与Package对象一起存储在一个单独的集合中。并且由映射器处理如下:
public InternetPackage fromDto(InternetPackageDto dto) {
var internetPackage = new InternetPackage();
internetPackage.setName(dto.getName());
internetPackage.setPrice(dto.getPrice());
internetPackage.setId(dto.getId());
internetPackage.setExtras(this.resolePackageExtras(dto));
internetPackage.setAttributes(this.resolePackageAttributes(dto));
return internetPackage;
}
private Flux<StoreableAttribute> resolePackageExtras(InternetPackageDto dto) {
return this.storeableAttributeService.resolveAttributes(dto.getExtras());
}
对于额外的和类似的属性。
和一个简单的控制器方法如下:
@PostMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public Mono<InternetPackageDto> update(@RequestBody InternetPackageDto incomingPackageDto) {
return this.packageService
.updatePackage(this.dtoMapper.fromDto(incomingPackageDto))
.map(this.dtoMapper::toDto);
}
当我提出帖子请求时,我会收到一个错误,说明
org.springframework.core.codec.CodecException: Type definition error: [simple type, class reactor.core.publisher.Flux]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `reactor.core.publisher.Flux` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (io.netty.buffer.ByteBufInputStream); line: 2, column: 13] (through reference chain: com.example.api.dto.InternetPackageDto["extras"])
更多信息:
- 我使用类
InternetPackageDto
作为请求对象和响应对象 - 我使用的是
Flux<String>
,而不是List<String>
,因为我不确定对列表进行阻塞解析是否是个好主意 - 属性分别存储和管理
- 以及在更新或插入程序包期间;如果包含了新的extra或attribute,那么db中的attributes集合将通过插入新的传入extra和attribute来更新
我可能犯了一个愚蠢的错误,因为我找不到关于这个问题的太多信息,或者我做得完全错误。
如有任何帮助,我们将不胜感激。
我认为你应该像这个一样做smth
public Mono<InternetPackageDto> toDto(InternetPackage entity) {
var internetPackage = new InternetPackageDto();
internetPackage.setName(entity.getName());
internetPackage.setPrice(entity.getPrice());
internetPackage.setId(entity.getId());
return Mono.zip(Mono.just(internetPackage), entity.getExtras().collectList(), entity.getAttributes().collectList())
.flatMap(tu->{
var dto = tu.getT1();
dto.setExtras(tu.getT2()); //To make it work in my local i made entity.getAttributes() as Flux<String> so here you will probably need to use .stream().map(dbItem->dbItem.getPropertyName())
dto.setPackageAttributes(tu.getT2());
return Mono.just(dto);
});
}