【问题标题】:How to send only a list of IDs in many-to-many spring boot JPA POST request instead of sending the full object's data如何在多对多 Spring Boot JPA POST 请求中仅发送 ID 列表,而不是发送完整对象的数据
【发布时间】:2022-11-12 05:58:14
【问题描述】:

我有 2 个 DTO“OrderItem”和“Ingredient”,两个类都有@ManyToMany注解:

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

我正在寻找使用以下 @PostMapping 控制器函数的 POST 请求添加一个新的 OrderItem:

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

当我向本地主机:8080/1/orderItem具有以下主体:

{
    "order":"1",
    "food":"burger",
    "quantity":"1"
}

它工作正常并创建了一个新的 order_item 数据库记录,但是当我使用以下正文发送相同的请求时:

{
    "order":"1",
    "food":"burger",
    "quantity":"1",
    "ingredients": [{"ingredientName":"leaf"}]
}

它失败并给出以下 SQL 错误:

java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'leaf' for key 'ingredient.PRIMARY'

我知道这条记录已经存在,但是我如何告诉 Spring Boot 我希望它寻找现有的成分而不是尝试创建新的成分?

我有一个丑陋的解决方案,那就是发送订单项对象旁边的字符串列表,其中每个元素代表一个主键成分类,然后通过调用存储库的元素逐个遍历该列表元素以获取成分对象然后手动将其添加到OrderItem.ingredients,但我确信这不是最好的解决方案。

【问题讨论】:

    标签: java spring-boot jpa many-to-many


    【解决方案1】:

    OrderItem 类上定义的关系ingredients 被视为级联策略观点的组合。因此,CascadeType.ALL 意味着尝试创建成分。 为避免这种情况,您可以更改此关系的方向反转 mappedBy 信息。 但是话又说回来,如果您在成分方面保留CascadeType.ALL,如果您使用现有的orderItem 创建成分,您将遇到麻烦。您可以使用CascadeType.ALL 赢得双方的胜利。

    检查JPA Hibernate many-to-many cascading

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 2021-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-20
      • 1970-01-01
      相关资源
      最近更新 更多