Issue
I am making a webshop in Java and I am currently working on the stock of the product. Everything is working fine, however I seem to get this confusing error which I don't know how to solve.
javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [nl.scalda.platenbaas.model.Stock#0191400002005]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:118) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:916) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:875) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.engine.spi.CascadingActions$6.cascade(CascadingActions.java:261) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:467) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:392) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:126) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:461) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:327) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:170) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:69) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:883) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
My method which saves the product and updates the stock:
@PostMapping("/products")
public ResponseEntity<Product> save(@RequestBody Product prod) {
if (!productRepo.existsById(prod.getEancode())) {
return ResponseEntity.ok().body(productRepo.save(prod));
}
prod.getStock().setCount(+prod.getStock().getCount());
return ResponseEntity.ok().body(productRepo.save(prod));
}
My Stock class:
@Id
private String stockId:
@JsonBackReference
@OneToOne(cascade = {PERSIST, MERGE}, fetch = FetchType.LAZY)
@JoinColumn(name = "eancode")
@MapsId
private Product product;
My Product class:
@JsonManagedReference
@OneToOne(cascade = {PERSIST, MERGE}, fetch = FetchType.LAZY, mappedBy = "product")
private Stock stock;
Solution
You should not update entities in that way, this only fits for creating new entities.
productRepo.save(prod)
Correct way is to first load entity by id (this would attach object to session), update it and then save
Product existing = productRepo.findById(prod.getId());
existing.getStock().setCount(+prod.getStock().getCount());
productRepo.save(existing);
But in your code you receive "unmanaged" (that is not attached to hibernate session) object with existing ID (!), update it and save. Of course it would give an error
Answered By - Nikolai Shevchenko
Answer Checked By - David Marino (JavaFixing Volunteer)