【问题标题】:JPA/Hibernate How to add duplicate values to a List<> with a @OneToMany mappingJPA/Hibernate 如何使用 @OneToMany 映射将重复值添加到 List<>
【发布时间】:2022-01-18 00:06:27
【问题描述】:

每次我尝试将重复的产品添加到客户端类时都会出错。

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "uk_8opk6otadh2pkvi9bghguwp89"
  Detail: Key (products_id)=(500010) already exists.

我的实体

@Entity
public class Client {
    @Id
    private String id;

    @OneToMany
    private List<Product> products;
}

@Entity
public class Product {
    @Id
    private String id;

    private Boolean foreign;
    private Integer price;
}

当我打电话给.save() 时,hibernate 正在尝试重新保存一个已经存在的产品。我相信这是由于它级联的方式。

public Client addNewProduct(Client client, Product newProduct) {
    List<Product> products = client.getProducts();
    products.add(newProduct);
    client.setProducts(products);
    return clientRepository.save(client);
}

我只是希望能够将重复项添加到列表。我相信这是 & 应该是一个单向的关系。

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    这不适用于您当前的关系,我不明白您为什么要添加重复项,但如果必须,那么您必须为此创建一个新实体。一个例子是这样的:

    @Entity
    public class ProductBatch {
    
      @Id
      private String id;
    
      @OneToOne
      private Product product;
    
      private Integer count;
    
      // getter & setter
    }
    

    然后你像这样改变你的Client

    @Entity
    public class Client {
    
        @Id
        private String id;
    
        @OneToMany
        private List<ProductBatch> products;
    }
    

    这使您的addNewProduct 函数可以实现类似的功能:

    public Client addNewProduct(Client client, Product newProduct) {
        List<ProductBatch> products = client.getProducts();
        boolean exists = false;
        for(ProductBatch product : products) {
            if(product.getProduct().equals(newProduct)) {
                product.setCount(product.getCount() + 1);
                exists = true;
            }
        }
        if(!exists) {
            BatchProduct product = new BatchProduct();
            product.setProduct(newProduct);
            product.setCount(0);
            products.add(product);
        }
        client.setProducts(products);
        return clientRepository.save(client);
    }
    

    【讨论】:

    • 我猜 ProductBatch 作为一个中间实体,如果我们只是在 Product 中存储整数计数,甚至是没有必要的?甚至 Map 也可以工作?
    • @turbofood 该地图的设置不必要地复杂,最终将实现与 ProductBatch 相同的目的。您不能将整数计数存储在产品中,因为多个客户可以购买不同数量的同一产品,因此您需要一个中间实体来解决此问题
    • 啊,好点子。好的,看起来需要一个中间人。谢谢大家的帮助!
    【解决方案2】:

    这与 JPA 或 Hibernate 无关。约束是数据库约束,它是正确的。如果外键已经是表的一部分,尝试再次添加它,就会违反此约束。 ID 是唯一的,它应该保持这种状态。所以添加重复项(至少具有相同的 ID)将不起作用。

    【讨论】:

    • 那么即使允许使用 List 又有什么意义呢?这完全是误导。
    猜你喜欢
    • 1970-01-01
    • 2019-02-24
    • 2018-10-14
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-06
    • 1970-01-01
    相关资源
    最近更新 更多