以JPA中的多对多关系防止联接表中的重复条目

问题描述 投票:5回答:2

我正在使用EclipseLink 2.5.1(和Hibernate 4.3.5最终版)。给定MySQL中的下表。

  • 产品
  • prod_colour(联接表)
  • 颜色

产品及其颜色之间存在多对多关系。

产品可以具有多种颜色,而颜色又可以与多种产品相关联。这些表在数据库中表示了这种关系。

prod_colour表在其相关父表prod_idcolour_id中分别具有两个参考列productcolour

很明显,实体类Product具有颜色列表-java.util.List<Colour>,其命名为colourList

实体类Colour具有产品列表-java.util.List<Product>,名称为productList


[Colour实体中的关系:

public class Colour implements Serializable {

    @JoinTable(name = "prod_colour", joinColumns = {
        @JoinColumn(name = "colour_id", referencedColumnName = "prod_id")}, inverseJoinColumns = {
        @JoinColumn(name = "prod_id", referencedColumnName = "colour_id")})
    @ManyToMany(mappedBy = "colourList", fetch = FetchType.LAZY)
    private List<Product> productList; //Getter and setter.

    //---Utility methods---

    //Add rows to the prod_colour table.
    public void addToProduct(Product product) {
        this.getProductList().add(product);
        product.getColourList().add(this);
    }

    //Delete rows from the prod_colour table.
    public void removeFromProduct(Product product) {
        this.getProductList().remove(product);
        product.getColourList().remove(this);
    }
}

Product实体中的关系:

public class Product implements Serializable {

    @JoinTable(name = "prod_colour", joinColumns = {
        @JoinColumn(name = "prod_id", referencedColumnName = "prod_id")}, inverseJoinColumns = {
        @JoinColumn(name = "colour_id", referencedColumnName = "colour_id")})
    @ManyToMany(fetch = FetchType.LAZY)
    private List<Colour> colourList; //Getter and setter.
}

从关联的EJB中,插入操作如下执行。

@Override
@SuppressWarnings("unchecked")
public boolean insert(List<Colour> colours, Product product)
{
    int i=0;
    Long prodId=product.getProdId();
    for(Colour colour:colours)
    {
        Product p = entityManager.getReference(Product.class, prodId);
        colour.addToProduct(p);

        if(++i%49==0)
        {
            entityManager.flush();
        }
        entityManager.merge(colour);
        entityManager.merge(p);
    }
    return true;
}

一切正常。


[当尝试重复的行(与相同的Colour实体关联的相同Product实体]时,它们也被插入到我不希望发生的prod_colour表中。

我是否需要执行一些额外的条件检查以避免重复插入,或者EclipseLink / Hibernate具有某种机制来防止重复插入?

hibernate jpa many-to-many eclipselink jpa-2.1
2个回答
7
投票

这也让我感到惊讶。我一直在想,它使连接表中的引用列作为复合主键,但事实并非如此。如果要具有唯一记录,请尝试使用Set而不是List或使用复合主键(color_id,product_id)创建自己的ManyToMany关系表。我没有更好的主意。


0
投票

您可以在JoinTable上指定一个uniqueConstraints,如下所示:

@JoinTable(name = "prod_colour", joinColumns = {
        @JoinColumn(name = "prod_id", referencedColumnName = "prod_id")}, inverseJoinColumns = {
        @JoinColumn(name = "colour_id", referencedColumnName = "colour_id")}, uniqueConstraints = @UniqueConstraint(columnNames = {
                            "colour_id", "prod_id" }))

这将防止直接对表并通过您的应用程序代码执行直接sql时条目的重复。

© www.soinside.com 2019 - 2024. All rights reserved.