java - Hibernate many to many: A collection with cascade all-delete-orphan -
i have 2 entities, purchase , product. have many many relationship:
purchase >-------purchaseproduct---------< product
beteween them have mapped entities together. works fine while saving or deleting purchase. exceptes when perform update, parent (purchase update) , children (linecommand) won't updated(means delete old children database , insert new ones).
here ddl both purchase , product , association: linecommand:
purchase:
create table purchase ( idpurchase serial not null, code character varying(50), date timestamp without time zone, totalht double precision, tva double precision, totalttc double precision, constraint purchase_pkey primary key (idpurchase) )
product:
create table product ( idproduct serial primary key, namear varchar(50), namefr varchar(50), preference varchar(50), qtystart double precision, qtyinhand double precision, sellprice double precision , purchaseprice double precision, taxe double precision );
linecommand:
create table purchaseproduct ( idpurchase integer, idproduct integer, qty double precision, price double precision, primary key(idpurchase,idproduct), foreign key(idpurchase) references purchase(idpurchase), foreign key(idproduct) references product(idproduct) );
the mapping above entities:
@entity @table(name = "purchase") @access(accesstype.property) public class purchase { private longproperty idpurchase; private stringproperty codepurchase; private objectproperty<localdate> datepurchase; private doubleproperty totalht; private doubleproperty tva; private doubleproperty totalttc; private set<linecommand> lineitems = new hashset<linecommand>(0); public purchase() { this.idpurchase = new simplelongproperty(); this.codepurchase = new simplestringproperty(); this.datepurchase = new simpleobjectproperty<>(); this.totalht = new simpledoubleproperty(); this.tva = new simpledoubleproperty(); this.totalttc = new simpledoubleproperty(); } @id @generatedvalue(strategy = generationtype.sequence, generator = "purchase_seq_gen") @sequencegenerator(name = "purchase_seq_gen", sequencename = "purchase_idpurchase_seq", initialvalue = 1, allocationsize = 1) @column(name = "idpurchase", unique = true, nullable = false) public long getidpurchase() { return idpurchase.get(); } public longproperty idpurchaseproperty() { return idpurchase; } public void setidpurchase(long idpurchase) { this.idpurchase.set(idpurchase); } @column(name = "code") public string getcodepurchase() { return codepurchase.get(); } public stringproperty codepurchaseproperty() { return codepurchase; } public void setcodepurchase(string codepurchase) { this.codepurchase.set(codepurchase); } @column(name = "date") @convert(converter = localdatepersistanceconverter.class) public localdate getdatepurchase() { return datepurchase.get(); } public objectproperty<localdate> datepurchaseproperty() { return datepurchase; } public void setdatepurchase(localdate datepurchase) { this.datepurchase.set(datepurchase); } @column(name = "totalht") public double gettotalht() { return totalht.get(); } public doubleproperty totalhtproperty() { return totalht; } public void settotalht(double totalht) { this.totalht.set(totalht); } @column(name = "tva") public double gettva() { return tva.get(); } public doubleproperty tvaproperty() { return tva; } public void settva(double tva) { this.tva.set(tva); } @column(name = "totalttc") public double gettotalttc() { return totalttc.get(); } public doubleproperty totalttcproperty() { return totalttc; } public void settotalttc(double totalttc) { this.totalttc.set(totalttc); } @onetomany(mappedby = "primarykey.purchase", fetch = fetchtype.eager, cascade = cascadetype.all, orphanremoval = true) @fetch(value = fetchmode.subselect) public set<linecommand> getlineitems() { return this.lineitems; } public void setlineitems(set<linecommand> lineitems) { this.lineitems = lineitems; } @override public boolean equals(object obj) { if (obj == null) { return false; } else { if (this.idpurchase.getvalue() == ((purchase) obj).getidpurchase()) return true; else return false; } } }
product :
@entity @table(name = "product") @access(accesstype.property) public class product { private longproperty idproduct; private stringproperty namear; private stringproperty namefr; private stringproperty preference; private doubleproperty qtystart; private doubleproperty qtyinhand; private doubleproperty sellprice; private doubleproperty purchaseprice; private doubleproperty taxe; private set<linecommand> items = new hashset<linecommand>(); public void setidproduct(long idproduct) { this.idproduct.set(idproduct); } public product() { idproduct = new simplelongproperty(); namear = new simplestringproperty(); namefr = new simplestringproperty(); preference = new simplestringproperty(); qtystart = new simpledoubleproperty(); qtyinhand = new simpledoubleproperty(); sellprice = new simpledoubleproperty(); purchaseprice = new simpledoubleproperty(); taxe = new simpledoubleproperty(); } @id @generatedvalue(strategy = generationtype.sequence, generator = "product_seq_gen") @sequencegenerator(name = "product_seq_gen", sequencename = "product_idproduct_seq", initialvalue = 1, allocationsize = 1) @column(name = "idproduct", unique = true, nullable = false) public long getidproduct() { return idproduct.get(); } public longproperty idproductproperty() { return idproduct; } public void setidproduct(long idproduct) { this.idproduct.set(idproduct); } @column(name = "namear") public string getnamear() { return namear.get(); } public stringproperty namearproperty() { return namear; } public void setnamear(string namear) { this.namear.set(namear); } @column(name = "namefr") public string getnamefr() { return namefr.get(); } public stringproperty namefrproperty() { return namefr; } public void setnamefr(string namefr) { this.namefr.set(namefr); } @column(name = "preference") public string getpreference() { return preference.get(); } public stringproperty preferenceproperty() { return preference; } public void setpreference(string preference) { this.preference.set(preference); } @column(name = "qtystart") public double getqtystart() { return qtystart.get(); } public doubleproperty qtystartproperty() { return qtystart; } public void setqtystart(double qtystart) { this.qtystart.set(qtystart); } @column(name = "qtyinhand") public double getqtyinhand() { return qtyinhand.get(); } public doubleproperty qtyinhandproperty() { return qtyinhand; } public void setqtyinhand(double qtyinhand) { this.qtyinhand.set(qtyinhand); } @column(name = "sellprice") public double getsellprice() { return sellprice.get(); } public doubleproperty sellpriceproperty() { return sellprice; } public void setsellprice(double sellprice) { this.sellprice.set(sellprice); } @column(name = "purchaseprice") public double getpurchaseprice() { return purchaseprice.get(); } public doubleproperty purchasepriceproperty() { return purchaseprice; } public void setpurchaseprice(double purchaseprice) { this.purchaseprice.set(purchaseprice); } @column(name = "taxe") public double gettaxe() { return taxe.get(); } public doubleproperty taxeproperty() { return taxe; } public void settaxe(double taxe) { this.taxe.set(taxe); } @onetomany(mappedby = "primarykey.product", cascade = cascadetype.all) public set<linecommand> getitems() { return this.items; } public void setitems(set<linecommand> lineitems) { this.items = lineitems; } @override public boolean equals(object obj) { if (obj == null) { return false; } else { if (this.idproduct.getvalue() == ((product) obj).getidproduct()) return true; else return false; } } }
linecommand:
@entity @table(name = "purchaseproduct") @access(accesstype.property) @associationoverrides({ @associationoverride(name = "primarykey.product", joincolumns = @joincolumn(name = "idproduct")), @associationoverride(name = "primarykey.purchase", joincolumns = @joincolumn(name = "idpurchase"))}) public class linecommand implements serializable { // compostie key; private linecommandid primarykey = new linecommandid(); private doubleproperty sellprice = new simpledoubleproperty(); private doubleproperty qty = new simpledoubleproperty(); private doubleproperty subtotal = new simpledoubleproperty(); public linecommand() { this.sellprice = new simpledoubleproperty(); this.qty = new simpledoubleproperty(); this.subtotal = new simpledoubleproperty(); numberbinding subtotalbinding = bindings.multiply(this.qty, this.sellprice); subtotal.bind(subtotalbinding); } @embeddedid public linecommandid getprimarykey() { return primarykey; } public void setprimarykey(linecommandid primarykey) { this.primarykey = primarykey; } @transient public product getproduct() { return primarykey.getproduct(); } public void setproduct(product product) { primarykey.setproduct(product); } @transient public purchase getpurchase() { return primarykey.getpurchase(); } public void setpurchase(purchase purchase) { primarykey.setpurchase(purchase); } @column(name = "price") public double getsellprice() { return sellprice.get(); } public doubleproperty sellpriceproperty() { return sellprice; } public void setsellprice(double sellprice) { this.sellprice.set(sellprice); } @column(name = "qty") public double getqty() { return qty.get(); } public doubleproperty qtyproperty() { return qty; } public void setqty(double qty) { this.qty.set(qty); } @transient public double getsubtotal() { return subtotal.get(); } public doubleproperty subtotalproperty() { return subtotal; } public void setsubtotal(double subtotal) { this.subtotal.set(subtotal); } @override public boolean equals(object obj) { if (obj == null) { return false; } else { product product = ((linecommand) obj).getproduct(); purchase purchase = ((linecommand) obj).getpurchase(); if (getproduct().equals(product)) return true; else return false; } } }
since save , delete methodes works put code of update methode.
public boolean update(purchase obj) { try { if (!session.isopen()) session = databaseutil.getsessionfactory().opensession(); session.begintransaction(); purchase purchase = session.get(purchase.class, obj.getidpurchase()); purchase.setcodepurchase(obj.getcodepurchase()); purchase.setdatepurchase(obj.getdatepurchase()); purchase.settotalht(obj.gettotalht()); purchase.settva(obj.gettva()); purchase.settotalttc(obj.gettotalttc()); purchase.getlineitems().clear(); purchase.setlineitems(obj.getlineitems()); session.gettransaction().commit(); session.close(); return true; } catch (exception e) { e.printstacktrace(); return false; } }
after executing above function exception:
org.hibernate.hibernateexception: collection cascade="all-delete-orphan" no longer referenced owning entity instance: model.purchase.lineitems @ org.hibernate.engine.internal.collections.processdereferencedcollection(collections.java:99) @ org.hibernate.engine.internal.collections.processunreachablecollection(collections.java:50) @ org.hibernate.event.internal.abstractflushingeventlistener.flushcollections(abstractflushingeventlistener.java:243) @ org.hibernate.event.internal.abstractflushingeventlistener.flusheverythingtoexecutions(abstractflushingeventlistener.java:86) @ org.hibernate.event.internal.defaultflusheventlistener.onflush(defaultflusheventlistener.java:38) @ org.hibernate.internal.sessionimpl.flush(sessionimpl.java:1282) @ org.hibernate.internal.sessionimpl.managedflush(sessionimpl.java:465) @ org.hibernate.internal.sessionimpl.flushbeforetransactioncompletion(sessionimpl.java:2963) @ org.hibernate.internal.sessionimpl.beforetransactioncompletion(sessionimpl.java:2339) @ org.hibernate.engine.jdbc.internal.jdbccoordinatorimpl.beforetransactioncompletion(jdbccoordinatorimpl.java:485) @ org.hibernate.resource.transaction.backend.jdbc.internal.jdbcresourcelocaltransactioncoordinatorimpl.beforecompletioncallback(jdbcresourcelocaltransactioncoordinatorimpl.java:147) @ org.hibernate.resource.transaction.backend.jdbc.internal.jdbcresourcelocaltransactioncoordinatorimpl.access$100(jdbcresourcelocaltransactioncoordinatorimpl.java:38) @ org.hibernate.resource.transaction.backend.jdbc.internal.jdbcresourcelocaltransactioncoordinatorimpl$transactiondrivercontrolimpl.commit(jdbcresourcelocaltransactioncoordinatorimpl.java:231) @ org.hibernate.engine.transaction.internal.transactionimpl.commit(transactionimpl.java:65) @ dao.purchasedao.update(purchasedao.java:41) @ controller.purchase.purchasecontroller.btnsaveclicked(purchasecontroller.java:349) @ sun.reflect.nativemethodaccessorimpl.invoke0(native method) @ sun.reflect.nativemethodaccessorimpl.invoke(nativemethodaccessorimpl.java:62) @ sun.reflect.delegatingmethodaccessorimpl.invoke(delegatingmethodaccessorimpl.java:43) @ java.lang.reflect.method.invoke(method.java:497) @ sun.reflect.misc.trampoline.invoke(methodutil.java:71) @ sun.reflect.generatedmethodaccessor1.invoke(unknown source) @ sun.reflect.delegatingmethodaccessorimpl.invoke(delegatingmethodaccessorimpl.java:43) @ java.lang.reflect.method.invoke(method.java:497) @ sun.reflect.misc.methodutil.invoke(methodutil.java:275) @ javafx.fxml.fxmlloader$methodhandler.invoke(fxmlloader.java:1767) @ javafx.fxml.fxmlloader$controllermethodeventhandler.handle(fxmlloader.java:1653) @ com.sun.javafx.event.compositeeventhandler.dispatchbubblingevent(compositeeventhandler.java:86) @ com.sun.javafx.event.eventhandlermanager.dispatchbubblingevent(eventhandlermanager.java:238) @ com.sun.javafx.event.eventhandlermanager.dispatchbubblingevent(eventhandlermanager.java:191) @ com.sun.javafx.event.compositeeventdispatcher.dispatchbubblingevent(compositeeventdispatcher.java:59) @ com.sun.javafx.event.basiceventdispatcher.dispatchevent(basiceventdispatcher.java:58) @ com.sun.javafx.event.eventdispatchchainimpl.dispatchevent(eventdispatchchainimpl.java:114) @ com.sun.javafx.event.basiceventdispatcher.dispatchevent(basiceventdispatcher.java:56) @ com.sun.javafx.event.eventdispatchchainimpl.dispatchevent(eventdispatchchainimpl.java:114) @ com.sun.javafx.event.basiceventdispatcher.dispatchevent(basiceventdispatcher.java:56) @ com.sun.javafx.event.eventdispatchchainimpl.dispatchevent(eventdispatchchainimpl.java:114) @ com.sun.javafx.event.basiceventdispatcher.dispatchevent(basiceventdispatcher.java:56) @ com.sun.javafx.event.eventdispatchchainimpl.dispatchevent(eventdispatchchainimpl.java:114) @ com.sun.javafx.event.eventutil.fireeventimpl(eventutil.java:74) @ com.sun.javafx.event.eventutil.fireevent(eventutil.java:49) @ javafx.event.event.fireevent(event.java:198) @ javafx.scene.node.fireevent(node.java:8390) @ javafx.scene.control.button.fire(button.java:185) @ com.sun.javafx.scene.control.behavior.buttonbehavior.mousereleased(buttonbehavior.java:182) @ com.sun.javafx.scene.control.skin.behaviorskinbase$1.handle(behaviorskinbase.java:96) @ com.sun.javafx.scene.control.skin.behaviorskinbase$1.handle(behaviorskinbase.java:89) @ com.sun.javafx.event.compositeeventhandler$normaleventhandlerrecord.handlebubblingevent(compositeeventhandler.java:218) @ com.sun.javafx.event.compositeeventhandler.dispatchbubblingevent(compositeeventhandler.java:80) @ com.sun.javafx.event.eventhandlermanager.dispatchbubblingevent(eventhandlermanager.java:238) @ com.sun.javafx.event.eventhandlermanager.dispatchbubblingevent(eventhandlermanager.java:191) @ com.sun.javafx.event.compositeeventdispatcher.dispatchbubblingevent(compositeeventdispatcher.java:59) @ com.sun.javafx.event.basiceventdispatcher.dispatchevent(basiceventdispatcher.java:58) @ com.sun.javafx.event.eventdispatchchainimpl.dispatchevent(eventdispatchchainimpl.java:114) @ com.sun.javafx.event.basiceventdispatcher.dispatchevent(basiceventdispatcher.java:56) @ com.sun.javafx.event.eventdispatchchainimpl.dispatchevent(eventdispatchchainimpl.java:114) @ com.sun.javafx.event.basiceventdispatcher.dispatchevent(basiceventdispatcher.java:56) @ com.sun.javafx.event.eventdispatchchainimpl.dispatchevent(eventdispatchchainimpl.java:114) @ com.sun.javafx.event.basiceventdispatcher.dispatchevent(basiceventdispatcher.java:56) @ com.sun.javafx.event.eventdispatchchainimpl.dispatchevent(eventdispatchchainimpl.java:114) @ com.sun.javafx.event.eventutil.fireeventimpl(eventutil.java:74) @ com.sun.javafx.event.eventutil.fireevent(eventutil.java:54) @ javafx.event.event.fireevent(event.java:198) @ javafx.scene.scene$mousehandler.process(scene.java:3758) @ javafx.scene.scene$mousehandler.access$1500(scene.java:3486) @ javafx.scene.scene.impl_processmouseevent(scene.java:1762) @ javafx.scene.scene$scenepeerlistener.mouseevent(scene.java:2495) @ com.sun.javafx.tk.quantum.glassvieweventhandler$mouseeventnotification.run(glassvieweventhandler.java:350) @ com.sun.javafx.tk.quantum.glassvieweventhandler$mouseeventnotification.run(glassvieweventhandler.java:275) @ java.security.accesscontroller.doprivileged(native method) @ com.sun.javafx.tk.quantum.glassvieweventhandler.lambda$handlemouseevent$350(glassvieweventhandler.java:385) @ com.sun.javafx.tk.quantum.glassvieweventhandler$$lambda$431/1622936725.get(unknown source) @ com.sun.javafx.tk.quantum.quantumtoolkit.runwithoutrenderlock(quantumtoolkit.java:404) @ com.sun.javafx.tk.quantum.glassvieweventhandler.handlemouseevent(glassvieweventhandler.java:384) @ com.sun.glass.ui.view.handlemouseevent(view.java:555) @ com.sun.glass.ui.view.notifymouse(view.java:927) @ com.sun.glass.ui.win.winapplication._runloop(native method) @ com.sun.glass.ui.win.winapplication.lambda$null$145(winapplication.java:101) @ com.sun.glass.ui.win.winapplication$$lambda$38/673617397.run(unknown source) @ java.lang.thread.run(thread.java:745)
i hope clear identify main problem.
you setting new lineitems
collection instance on purchase
.
replace:
purchase.setlineitems(obj.getlineitems())
with:
purchase.getlineitems().addall(obj.getlineitems())
Comments
Post a Comment