由自己的实体实现的“一对多”和“多对一”协会;违反了唯一约束

时间:2012-07-10 17:03:53

标签: jpa

我想实现如下映射。我有一些产品和文章。一个产品有很多相关的文章。此外,此关系具有特殊属性,如返回代码。所以关联表应该是这样的。

Product_FK | Article_FK | return code
       1   |    1       |      0
       1   |    1       |      1
       1   |    2       |      1

目前我已经意识到这有两个联想。 “一个(产品)到多个(关系表)”和“多个(相关表)到一个(文章)”关联。

实体注释为休耕:

产品实体:

@Entity(name = "product")
@Table(name = "PRODUCT")
public class ProductDTO implements BaseEntityDTO {

   private static final long serialVersionUID = -6613561719098236228L;

   @Id
   @Column(name = "PRODUCT_PK")
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "product_pk_seq")
   @SequenceGenerator(name = "product_pk_seq", sequenceName = "product_pk_seq",   allocationSize = 1)
   protected Long pk;

   @OneToMany(cascade = CascadeType.ALL, mappedBy="product")
   private List<ProductArticleRelationDTO> product2article = new ArrayList<ProductArticleRelationDTO>();
  ...
  }

ProductArticleRelation实体:

@Entity(name = "productArticleRelation")
@Table(name = "PRODUCT_2_ARTICLE")
public class ProductArticleRelationDTO implements BaseEntityDTO {

       private static final long serialVersionUID = -1134854397447263839L;

   @Id
   @Column(name = "PRODUCT_2_ARTICLE_PK")
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "product2article_pk_seq")
   @SequenceGenerator(name = "product2article_pk_seq", sequenceName = "product2artikle_pk_seq", allocationSize = 1)
   protected Long pk;

   @Override
   public Long getPk() {
    return pk;
   }

   @Override
   public void setPk(long pk) {
    this.pk = Long.valueOf(pk);
   }

   @ManyToOne(cascade = CascadeType.ALL)
   @JoinColumn(name = "PRODUCT_FK")
   private ProductDTO product = null;

   @ManyToOne(cascade = CascadeType.ALL)
   @JoinColumn(name = "ARTICLE_FK")
   private ArticleDTO article = null;

   @Column
   private int returnCode;
     ...
 }

文章实体:

@Entity(name = "article")
@Table(name = "ARTICLE")
public class ArticleDTO implements BaseEntityDTO {

   private static final long serialVersionUID = 4397348044985703865L;

   @Id
   @Column(name = "ARTICLE_PK")
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "article_pk_seq")
   @SequenceGenerator(name = "article_pk_seq", sequenceName = "article_pk_seq", allocationSize = 1)
   protected Long pk;

   @Override
   public Long getPk() {
    return pk;
   }

   @Override
   public void setPk(long pk) {
    this.pk = Long.valueOf(pk);
   }

   @OneToMany(cascade = CascadeType.ALL, mappedBy = "article")
   private final List<ProductArticleRelationDTO> product2article = new ArrayList<ProductArticleRelationDTO>();

 ...
 }

我很确定注释是错误的。如果我想要保留添加了某些productArticleRelations的产品,我会遇到一个唯一的约束违规。

  for(ProductArticleRelationDTO relation : newProduct2Article) {
    product.addProduct2Article(relation);

  if(!em.contains(product))
        if(product.getPK() == null)
            em.persist(product);
        else 
        product = em.merge(product);
  else
    em.flush();

例外:

    Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
    Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: Unique Constraint (BC7_BPV.PK_ARTICLE) violated
    Error Code: 1
    Query: InsertObjectQuery(bc7.bpv.common.dto.ProductDTO@38f2f)

我不太确定的是,如果我需要productArticleRelation实体。这意味着是否有可能通过一个关联“一个(产品)到多个(aricles)”和一个以“返回代码”作为属性的特殊连接表来处理这种情况?

编辑:我忘记了,这种关系应该是双向的。

我在数据库中的表是休闲的(为了简化只显示重要的列):

PRODUCT:

 | PRODUCT_PK | ... |

ARTICLE:

 | ARTICLE_PK | ... |

PRODUCT_2_ARTICLE:

 | PRODUCT_2_ARTICLE_PK | PRODUCT_FK | ARTICLE_FK | RETURNCODE

1 个答案:

答案 0 :(得分:1)

首先:@JoinColumn应该在拥有方注释,即仅在ProductArticleRelationDTO注释。从ProductArticle完全删除它。要映射集合,应使用@OneToMany(cascade = CascadeType.ALL, mappedBy="property"),其中property是映射属性的java名称。在这种情况下,根据类别,“产品”或“文章”。

关于ProductArticleRelationDTO的必要性:只要您需要访问java中的返回代码,就需要它。如果它只是一个ManyToMany映射表并直接将Product映射到Article,你可以跳过它,但现在情况并非如此。

尝试此操作并发表评论,如果它无法解决您的问题。