@ManyToOne как заставить Json ссылаться на существующий внешний ключ?

#hibernate #rest #spring-data-jpa #spring-rest

#спящий режим #отдых #spring-data-jpa #spring-rest

Вопрос:

Я создаю RESTful-приложение для весенней загрузки. У меня есть две сущности: посетители:

 @Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private String email;
    private String gender;
}
  

и продукты

 @Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private int qty;
    private int price;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "customer_id", referencedColumnName = "id")
    private Customer customer;
}
  

Вот как я пытаюсь вставить Json через контроллер в объект OrderRequest:

 @PostMapping("/placeOrder")
    public Product saveOrder(@RequestBody OrderRequest request){
       return productRepository.save(request.getProduct());
    }
  

Класс OrderRequest:

 @Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderRequest {

    private Product product;
}
  

Классы репозитория являются стандартными:

 public interface ProductRepository extends JpaRepository<Product, Integer> {}
public interface CustomerRepository extends JpaRepository<Customer, Integer> {}
  

Я хочу, чтобы json выглядел так:

 {
   "product":{
       "name":"Mobile",
       "price":10000,
        "qty":1,
        "idCustomer": 1
   }
}
  

Вопрос: Как я могу сделать так, чтобы с уже существующей строкой в таблице Customer я отправлял на сервер Json, в котором я указал только параметры продукта и параметр внешнего ключа, который был бы ссылкой на строку Customer ??Спасибо

Ответ №1:

Не рекомендуется предоставлять объекты уровня сохраняемости на уровне контроллеров, потому что ваш API соединяется с внутренним представлением данных.

Распространенным способом реализации вашего требования является использование шаблона объекта передачи. То есть создать отдельные классы для использования в API. В вашем случае вы можете создать класс ProductTO со следующей структурой:

 public class ProductTO {
    private int id;
    private String name;
    private int qty;
    private int price;

    private int customerId;
}
  

Затем вы можете сопоставить поля между ProductTO и Product вручную или использовать любую библиотеку сопоставления (например: MapStruct) для автоматического копирования значений полей с одинаковыми именами в обоих классах.

Внешний ключ должен быть назначен вручную:

 Customer customer = this.customerRepo.findById(productTO.getCustomerId()).orElseThrow(() -> new YourException());
product.setCustomer(customer);
  

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

1. Как я могу реализовать это с помощью mapstruct? @Satiago