Search code examples
hibernaterestspring-data-jpaspring-rest

@ManyToOne how to make Json refer to existing foreign key?


I am making a Spring Boot RESTful application. I have two entities: Visitors:

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

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

and products

@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;
}

This is how I am trying to shove Json through the controller into the OrderRequest object:

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

OrderRequest class:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderRequest {

    private Product product;
}

The repository classes are standard:

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

I want json to look like this:

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

Question: How can I make it so that with an already existing row in the Customer table, I send Json to the server, in which I indicated only product parameters and a foreign key parameter that would be a reference to the Customer row ?? Thanks


Solution

  • It's not the best practice to expose the persistence-level entities in the controllers layer, because your API gets coupled to the internal representation of the data.

    The common way to implement your requirement is to use the Transfer Object Pattern. That is, create separate classes to use in the API. In your use case, you could create a ProductTO class with the following structure:

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

    Then you can map the fields between ProductTO and Product manually, or use any mapping library (for example: MapStruct) to copy automatically the values of the fields with the same name in both classes.

    The foreign key should be assigned manually:

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