I have 2 DTOs "OrderItem" and "Ingredient", both classes has @ManyToMany annotation:
@Entity
@Table
@NoArgsConstructor
@Data
public class OrderItem {
private @Id @GeneratedValue @NotNull long id;
@ManyToOne(optional = false)
@JoinColumn(nullable = false)
@OnDelete(action = OnDeleteAction.CASCADE)
private Order order;
@ManyToOne(optional = false)
@JoinColumn(nullable = false)
@OnDelete(action = OnDeleteAction.CASCADE)
private Food food;
private int quantity;
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(
name = "order_item_ingredient",
joinColumns = @JoinColumn(name = "order_item_id"),
inverseJoinColumns = @JoinColumn(name = "ingredient_name")
)
private Set<Ingredient> ingredients = new HashSet<>();
}
@Entity
@Table
@Data
@NoArgsConstructor
public class Ingredient {
private @Id String ingredientName;
private float basePrice;
private boolean addable;
@ManyToMany(mappedBy = "ingredients",cascade=CascadeType.ALL)
private Set<Food> foods= new HashSet<>();
@ManyToMany(mappedBy = "ingredients",cascade=CascadeType.ALL)
private Set<OrderItem> orderItems= new HashSet<>();
public Ingredient(String ingredientName, float basePrice, boolean addable) {
this.ingredientName = ingredientName.toLowerCase();
this.basePrice = basePrice;
this.addable = addable;
}
}
And I'm looking to add a new OrderItem using a POST request using the following @PostMapping controller function:
@PostMapping("{id}/orderItem")
public ResponseEntity<OrderItem> createMenuItem(
@PathVariable(value = "id") Long orderId,
@RequestBody OrderItem orderItem) {
Order order = orderService.getOrder(orderId)
.orElseThrow(() -> new ResourceNotFoundException("order '" + orderId + "' is not found"));
orderItem.setOrder(order);
orderItemRepository.save(orderItem);
return new ResponseEntity<>(orderItem, HttpStatus.CREATED);
}
When I send a post request to localhost:8080/1/orderItem with the following body:
{
"order":"1",
"food":"burger",
"quantity":"1"
}
It works fine and a new order_item database record is created, but when I send the same request with the following body:
{
"order":"1",
"food":"burger",
"quantity":"1",
"ingredients": [{"ingredientName":"leaf"}]
}
It fails and gives the following SQL error:
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'leaf' for key 'ingredient.PRIMARY'
I know that this record already exists, but how do I tell Spring Boot that I want it to look for an existing Ingredient instead of trying to create a new one?
I have an ugly solution in my mind, and that is to send the OrderItem object alongside a list of strings where each element represents a primary key for Ingredient class, then iterate through that list element by element calling the repository to get the Ingredient object then manually add it to OrderItem.ingredients, but I'm sure that is not the best solution out there.