jpa:更新新父实体的关系

时间:2016-08-11 11:49:06

标签: jpa eclipselink jpa-2.1

我有两个实体价格< -1 ---- 1-> PriceDetail 映射为 OneToOne

我如何处理这种关系的不同场景。所以我有一些情况,我总是想要一个新的价格和一个新的价格, 但我也可以只创建一个新价格并更新pricedetail(使用之前价格实体的数据)。 我目前的解决方案是删除pricedetail-entity,如何更新pricedetail-entity呢?

@Entity
class Price {

  @OneToOne(cascade=CascadeType.ALL,mappedBy = "price")
  private PriceDetail priceDetail;
}

@Entity
class PriceDetail {

  @OneToOne
  private Price price;
}

节省-方法:

EntityManage em = getEntityManager();

for (Price price : getAllPrices()){ 

  Price oldPrice =  Price.getById(price.getId());               

  if (!oldPrice.equals(price)){ //if we have price-changes

     if (PriceCatalog.entryExists(oldPrice)){ //if the current-price is in a catalog

      //current solution: remove entry from PriceDetail, but i want to update PriceDetail-Entity, pointing 
      //to the newly created price
      em.remove(oldPrice.getPriceDetail());
      em.commitTransaction();

      oldPrice.setActive(false);  //referenced price in PriceCatalog is now inactive                

      //sets id null, so that a new price-entity is created
      price.setId(null);            
      price.setActive(true);                        
      em.persist(price);   //also inserts a new price-detail

     }else {
      em.merge(price);
     }
   }                        
 }
 em.commitTransaction();

由于Price-Entity中的CascadeType.ALL-Annotation,JPA尝试插入新的PriceDetail-Entity。

接近1:

price.getPriceDetail().setId(oldPrice.getPriceDetail().getId());

- >错误:插入pricedetail违反了唯一约束:密钥已存在

方法2:

  //ommit cascade
  @OneToOne(mappedBy = "price")
  protected PriceDetail priceDetail;

然后方法1工作,但创建一个完整的新价格导致:   在同步期间,通过未标记为级联PERSIST的关系找到了新对象

1 个答案:

答案 0 :(得分:1)

在你的情况下,

方法2不是一个选项,这是进行双向一对一关联的正确映射:

//you must do this to handle the bidirectional association
  @OneToOne(mappedBy = "price")
  protected PriceDetail priceDetail;

现在问题是:price是一个新实体,然后entityManager将在price.getpriceDetail()上调用persit操作,因为cascade persist是自动触发的(不是级联合并),以避免这种奇怪的行为,你可以执行以下操作。 / p>

EntityManage em = getEntityManager();

for (Price price : getAllPrices()){ 

  Price oldPrice =  Price.getById(price.getId());               

  if (!oldPrice.equals(price)){ //if we have price-changes

     if (PriceCatalog.entryExists(oldPrice)){ //if the current-price is in a catalog

      //current solution: remove entry from PriceDetail, but i want to update PriceDetail-Entity, pointing 
      //to the newly created price
      //em.remove(oldPrice.getPriceDetail());
      //em.commitTransaction();

      oldPrice.setActive(false);  //referenced price in PriceCatalog is now inactive                

      PriceDetail priceDetailold = price.getPriceDetail();
      price.setPriceDetail(null);
      priceDetailold.setPrice(null);
      //sets id null, so that a new price-entity is created
      price.setId(null);            
      price.setActive(true);  

      em.persist(price);   //inserts a new price
      price.setPriceDetail(priceDetailold);
      em.merge(price);// attach the pricedetail to the price
  }else {
      em.merge(price);
  }
 }                      
}
em.commitTransaction();