jpa:更新新父实体的关系
jpa: update relationship for a new parent-entity
我有两个实体 Price<-1----1->PriceDetail 映射为 OneToOne.
我该如何处理这种关系的不同场景。所以我有这样的情况,我总是想要一个新的价格和一个新的价格细节,
但我也只能创建新价格并更新价格详情(使用来自先前价格实体的数据)。
我目前的解决方案是删除 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();
由于 CascadeType.ALL-Price-Entity 中的注释,JPA 尝试插入一个新的 PriceDetail-Entity。
方法一:
price.getPriceDetail().setId(oldPrice.getPriceDetail().getId());
-> 错误:插入 pricedetail 违反唯一约束:密钥已存在
方法二:
//ommit cascade
@OneToOne(mappedBy = "price")
protected PriceDetail priceDetail;
那么方法 1 可行,但创建一个全新的价格会导致:
在同步过程中,通过未标记为级联 PERSIST 的关系找到了一个新对象
方法 2 不适用于您的情况,这是执行双向一对一关联的正确映射:
//you must do this to handle the bidirectional association
@OneToOne(mappedBy = "price")
protected PriceDetail priceDetail;
现在的问题是:price 是一个新实体,然后 entityManager 将在 price.getpriceDetail() 上调用 persit 操作,因为级联持久化是自动触发的(不是级联合并)以避免这种奇怪的行为,您可以这样做以下。
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();
我有两个实体 Price<-1----1->PriceDetail 映射为 OneToOne.
我该如何处理这种关系的不同场景。所以我有这样的情况,我总是想要一个新的价格和一个新的价格细节, 但我也只能创建新价格并更新价格详情(使用来自先前价格实体的数据)。 我目前的解决方案是删除 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();
由于 CascadeType.ALL-Price-Entity 中的注释,JPA 尝试插入一个新的 PriceDetail-Entity。
方法一:
price.getPriceDetail().setId(oldPrice.getPriceDetail().getId());
-> 错误:插入 pricedetail 违反唯一约束:密钥已存在
方法二:
//ommit cascade
@OneToOne(mappedBy = "price")
protected PriceDetail priceDetail;
那么方法 1 可行,但创建一个全新的价格会导致: 在同步过程中,通过未标记为级联 PERSIST 的关系找到了一个新对象
方法 2 不适用于您的情况,这是执行双向一对一关联的正确映射:
//you must do this to handle the bidirectional association
@OneToOne(mappedBy = "price")
protected PriceDetail priceDetail;
现在的问题是:price 是一个新实体,然后 entityManager 将在 price.getpriceDetail() 上调用 persit 操作,因为级联持久化是自动触发的(不是级联合并)以避免这种奇怪的行为,您可以这样做以下。
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();