Reputation: 2480
I have 2 entities Product and ProductOptions with manytomany Relationship.
@Entity
public class Product {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String description;
private String productCategory;
private String optionDescription;
private BigDecimal productBasePrice;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="product_productoption",joinColumns=@JoinColumn(name="Product_id"), inverseJoinColumns=@JoinColumn(name="ProductOption_id"))
private Set<ProductOption>productOptions=new HashSet<>();
}
And
@Entity
public class ProductOption {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String productOptionDescription;
private BigDecimal optionPrice;
private BigDecimal optionPriceForSmall;
private BigDecimal optionPriceForNormal;
private BigDecimal optionPriceForFamily;
private BigDecimal optionPriceForParty;
@ManyToMany(mappedBy = "productOptions")
private Set<Product>product=new HashSet<>();
}
Data initialisation
private void initProducts() {
ProductOption productOpton1=new ProductOption("mit Cocktailsauce", new BigDecimal(0), null, null, null, null);
ProductOption productOpton2=new ProductOption("mit Joghurtsauce", new BigDecimal(0), null, null, null, null);
ProductOption productOpton3=new ProductOption("ohne Sauce", new BigDecimal(0), null, null, null, null);
Product product37= new Product("Falafel", ProductCategory.Vegatarische_Döner, "Wahl aus: mit Cocktailsauce, mit Joghurtsauce oder ohne Sauce.", new BigDecimal(5.00));
product37.getProductOptions().add(productOpton1);
product37.getProductOptions().add(productOpton2);
product37.getProductOptions().add(productOpton3);
productOpton1.getProduct().add(product37);
productOpton2.getProduct().add(product37);
productOpton3.getProduct().add(product37);
Product product38= new Product("Falafel Yufka Dürüm", ProductCategory.Vegatarische_Döner, "Wahl aus: mit Cocktailsauce, mit Joghurtsauce oder ohne Sauce.", new BigDecimal(5.50));
product38.getProductOptions().add(productOpton1);
product38.getProductOptions().add(productOpton2);
product38.getProductOptions().add(productOpton3);
productOpton1.getProduct().add(product38);
productOpton2.getProduct().add(product38);
productOpton3.getProduct().add(product38);
this.productRepository.save(product37);
this.productRepository.save(product38);
}
it gives me following exception
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: xx.xy.zz ProductOption
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:127) ~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118) ~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:726) ~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:694) ~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
at org.hibernate.engine.spi.CascadingActions$7.cascade(CascadingActions.java:298) ~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
but if i do not persist the product38
this.productRepository.save(product38);
then i do not have any problem . it seems like i cannot persist the same instance multiple times ?since productOption 1-3 are already persisted with product37 ?
product38.getProductOptions().add(productOpton1);
product38.getProductOptions().add(productOpton2);
product38.getProductOptions().add(productOpton3);
Do i have to create new instance everytime though content is same . Is there any workaround here ?
Please advice. Thanks.
**Update ** forget to mention that Equals is implemented in both the entities.
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ProductOption other = (ProductOption) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (optionPrice == null) {
if (other.optionPrice != null)
return false;
} else if (!optionPrice.equals(other.optionPrice))
return false;
if (optionPriceForFamily == null) {
if (other.optionPriceForFamily != null)
return false;
} else if (!optionPriceForFamily.equals(other.optionPriceForFamily))
return false;
if (optionPriceForNormal == null) {
if (other.optionPriceForNormal != null)
return false;
} else if (!optionPriceForNormal.equals(other.optionPriceForNormal))
return false;
if (optionPriceForParty == null) {
if (other.optionPriceForParty != null)
return false;
} else if (!optionPriceForParty.equals(other.optionPriceForParty))
return false;
if (optionPriceForSmall == null) {
if (other.optionPriceForSmall != null)
return false;
} else if (!optionPriceForSmall.equals(other.optionPriceForSmall))
return false;
if (productOptionDescription == null) {
if (other.productOptionDescription != null)
return false;
} else if (!productOptionDescription.equals(other.productOptionDescription))
return false;
return true;
}
Saving ProductOptions first and reusing them does not help either.
private void initProducts() {
ProductOption productOpton1=new ProductOption("mit Cocktailsauce", new BigDecimal(0), null, null, null, null);
ProductOption productOpton2=new ProductOption("mit Joghurtsauce", new BigDecimal(0), null, null, null, null);
ProductOption productOpton3=new ProductOption("ohne Sauce", new BigDecimal(0), null, null, null, null);
Product product37= new Product("Falafel", ProductCategory.Vegatarische_Döner, "Wahl aus: mit Cocktailsauce, mit Joghurtsauce oder ohne Sauce.", new BigDecimal(5.00));
product37.getProductOptions().add(productOpton1);
product37.getProductOptions().add(productOpton2);
product37.getProductOptions().add(productOpton3);
productOpton1.getProduct().add(product37);
productOpton2.getProduct().add(product37);
productOpton3.getProduct().add(product37);
Product product38= new Product("Falafel Yufka Dürüm", ProductCategory.Vegatarische_Döner, "Wahl aus: mit Cocktailsauce, mit Joghurtsauce oder ohne Sauce.", new BigDecimal(5.50));
product38.getProductOptions().add(productOpton1);
product38.getProductOptions().add(productOpton2);
product38.getProductOptions().add(productOpton3);
productOpton1.getProduct().add(product38);
productOpton2.getProduct().add(product38);
productOpton3.getProduct().add(product38);
this.productOptionRepository.save(productOpton1);
this.productOptionRepository.save(productOpton2);
this.productOptionRepository.save(productOpton3);
this.productRepository.save(product37);
this.productRepository.save(product38);
}
Upvotes: 0
Views: 265
Reputation: 152
You need @Transactional at the method initProducts if you want to save multiple different data in one method. The problem seems to be, that to the moment that you want to save product38 the ProductOptions not saved in DB yet. With @Transactional spring create a transaction and all operations will be performed.
Upvotes: 1