因此,我有一个VehicleDto:
class VehicleDto { private String someId private String vType; private CarDto car; private BikeDto bike; }
我需要在请求有效负载中包含CarDto或BikeDto。
在请求后的有效负载中,将存在多个字段,这些字段是VehicleDto的属性,例如,此处为someId。现在,此someId也是CarDto和BikeDto的一部分,以及是VehicleDto的子代的任何其他Dto。
因此,当我尝试保存到数据库中时,那里出现了一些问题。
if (vehicleDto.getVType().equals("CAR")) { this.saveCar(vehicleDto); } private boolean saveCar(TicketSoldCreateDto ticketSoldCreateDto) { CarDto carDto = ticketSoldCreateDto.getCar(); carDto is mapped to Car model // Now how do I map the rest of the fields in vehicleDto to Car model?? }
特级车:
@MappedSuperclass @Data public abstract class Vehicle extends AbstractBaseEntity { // fields same as vehicleDto }
童车:
@Entity @Data public class Car extends Vehicle { // Some fields }
我应该如何设计此类问题?
为什么不像实体那样对DTO使用继承而不是关联?然后使用一些映射器将这些DTO映射到实体并返回(我更喜欢mapstruct)。
我在github上做了一个完整的例子。
DTO的:
@Data @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(value = CarDto.class, name = "car"), @JsonSubTypes.Type(value = BikeDto.class, name = "bike") }) public class VehicleDto { private Long id; private String type; private Integer modelYear; } @Data public class BikeDto extends VehicleDto { private String frameType; } @Data public class CarDto extends VehicleDto { private Boolean isCabriolet; }
需要@JsonTypeInfo和@JsonSubTypes来自动解析中的DTO类型Controller。我的样本控制器接收到VehicleDto并尝试将其作为Bike实体与DtoMapper和存储在数据库中VehicleService。最后一步- 它再次从数据库中读取它并以响应BikeDto。
Controller
VehicleDto
Bike
DtoMapper
VehicleService
BikeDto
@Controller public class SampleController { @Autowired private VehicleService vehicleService; @Autowired private DtoMapper mapper; @PostMapping("/testDto") @ResponseBody @Transactional public BikeDto testDto(@RequestBody VehicleDto vehicleDto) { if (vehicleDto instanceof BikeDto) vehicleService.saveBike(mapper.toBikeEntity((BikeDto) vehicleDto)); return mapper.toBikeDto(vehicleService.getBike(vehicleDto.getId())); } }
对于DtoMapper我使用过的Mapstruct,它可以将我的Bike实体来回转换BikeDto:
@Mapper(componentModel = "spring") @Component public interface DtoMapper { @Mapping(target = "type", constant = "bike") BikeDto toBikeDto(Bike entity); Bike toBikeEntity(BikeDto dto); }
最后,为该示例测试类。它BikeDto作为POST正文传递,并期望它返回。
@RunWith(SpringRunner.class) @SpringBootTest @ActiveProfiles("scratch") public class SampleDataJpaApplicationTests { @Autowired private WebApplicationContext context; private MockMvc mvc; @Before public void setUp() { this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build(); } @Test public void testDto() throws Exception { BikeDto bikeDto = new BikeDto(); bikeDto.setId(42L); bikeDto.setType("bike"); bikeDto.setModelYear(2019); bikeDto.setFrameType("carbon"); Gson gson = new Gson(); String json = gson.toJson(bikeDto); this.mvc.perform(post("/testDto").contentType(MediaType.APPLICATION_JSON).content(json)) .andExpect(status().isOk()) .andExpect(content().json(json)); } }
POST(BikeDto)正文:
{ "id":42, "type":"bike", "modelYear":2019, "frameType":"carbon" }
您可以在github上查看完整示例中的其他类(实体,服务,存储库)。