Spring Boot API Rest с отношениями DTO и @manytoone — лучшая практика

#java #spring #spring-boot #spring-data #dto

#java #spring #spring-boot #spring-данные #dto

Вопрос:

У меня следующая конфигурация:

ProductPriceEntity

 @Entity
@Table(name = "PRODUCTPRICE")
public class ProductPriceEntity {

    ...

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "SUPERMARKET_STORE_ID", nullable = false)
    private SupermarketStoreEntity store;

    ...
}
  

ProductPriceNewRequest

 @Setter @Getter
public class ProductPriceNewRequest {

    ...

    private Long storeId;

    ...

}
  

ProductPriceControllerImpl

 @PostMapping
@ResponseStatus(HttpStatus.CREATED)
public ResponseEntity<ProductPriceResponse> save(@PathVariable(value = "product_id", required = true) Long productId, @RequestBody @Valid ProductPriceNewRequest productPriceNewRequest) {
    ProductEntity productEntity = productService.findById(productId);

    ProductPriceEntity productPriceEntity = modelMapper.map(productPriceNewRequest, ProductPriceEntity.class);

    productPriceEntity.setProduct(productEntity);
    productPriceEntity = service.insert(productPriceEntity);

    URI location = ServletUriComponentsBuilder.fromCurrentRequest()
            .path("/{id}")
            .buildAndExpand(productPriceEntity.getId())
            .toUri();


    ProductPriceResponse productPriceResponse = modelMapper.map(productPriceEntity, ProductPriceResponse.class);

    return ResponseEntity.created(location).body(productPriceResponse);

}
  

ProductPriceResponse

 @Getter @Setter
public class ProductPriceResponse {

    ...

    private String supermarket;
    private String store;

    ...
}
  

Это работает, но я не могу вернуть DTO. Супермаркет и магазин равны нулю для ProductPriceResponse.

введите описание изображения здесь

Ну, тогда я изменил каскад отношений атрибутов хранилища.

 @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "SUPERMARKET_STORE_ID", nullable = false)
private SupermarketStoreEntity store;
  

И я получил эту ошибку:

«отдельная сущность передана в persist: model.SupermarketStoreEntity; вложенным исключением является org.hibernate.PersistentObjectException: отдельная сущность передается в persist: model.SupermarketStoreEntity»

Это имеет смысл. Modelmapper преобразует длинный StoreID в SupermarketStoreEntity с единственным идентификатором и отсоединяется…

наконец, мой вопрос: какова наилучшая практика?

Должен ли я получать StoreID и не преобразовываться в отделенный от SupermarketStoreEntity и находить SupermarketStoreEntity с вашим StoreID в ProductPriceControllerImpl?

Или нет. Должен ли я удалить каскад и после сохранения ProductPriceEntity я должен получить сохраненный ProductPriceEntity? Я подозреваю, что магазин и супермаркет все равно получат null, потому что каскада там нет.

спасибо всем

Ответ №1:

Думаю, лучше всего ввести класс @Service, где у вас есть метод с аннотацией @Transactional . Служба внедряется в контроллер, и там происходит вся загрузка и сохранение объектов. Это должно помочь с ошибкой отсоединения.

Я не большой поклонник атрибута cascade и предпочел бы делать это в коде, но это скорее мнение.

Может быть, вы хотите взглянуть на https://bootify.io — вы можете определить свою базу данных с помощью REST api там и получить представление о лучших практиках для контроллеров и служб.:)

Комментарии:

1. Я уже использую класс обслуживания с транзакционным и метод с транзакционным тоже …. но моя проблема сохраняется! Если я использую CascadeType.ALL (или CascadeType. СОХРАНЯЕТСЯ) Я получил ошибку отсоединения…. Если я не использую каскад, он работает нормально, но я не получаю детализации хранилища, потому что каскада нет. Я не знаю! Должен ли я получить объект хранилища перед сохранением? Я хотел бы просто передать идентификатор хранилища и объекта хранилища выборки данных Spring до сохранения ….. или после …. для я использую в своем ответе….

2. Для меня звучит так, как будто отсоединение происходит от фактического каскада: вы удаляете объект, и из-за каскада StoreDetails также удаляется. Теперь имеющиеся у вас данные хранилища отсоединены, поскольку они больше не существуют. Я бы попытался сделать это с помощью Cascade NONE и удалить связанные объекты отдельно. Но действительно сложно помочь вам дальше удаленно.