Hi,
I am experiencing the now famous ManyToMany hiberante entity manager bug. I
have read the many post on the forum and tried the alternative : using Set
instead of collections, using Lazy Fetch type but none of that works for me.
The problem is as follow :
A product belongs to many Classes of Products
A Product belongs to many Famillies of Products
So, when creating a product, the product famillies and Classes can be selected.
|
| import java.io.Serializable;
| import java.util.Set;
| import java.util.TreeSet;
|
| import javax.persistence.CascadeType;
| import javax.persistence.Column;
| import javax.persistence.Entity;
| import javax.persistence.FetchType;
| import javax.persistence.GeneratedValue;
| import javax.persistence.GenerationType;
| import javax.persistence.Id;
| import javax.persistence.JoinColumn;
| import javax.persistence.JoinTable;
| import javax.persistence.ManyToMany;
| import javax.persistence.OneToOne;
| import javax.persistence.Table;
| import javax.persistence.Version;
|
| import com.elina.commercialis.server.stock.classification.Classe;
| import com.elina.commercialis.server.stock.classification.Famille;
|
| @Entity
| @Table(name = "produit")
| public class Produit implements Serializable, Comparable
| {
|
| private long produitID;
|
| private String codeProduit;
|
| private String libelleProduit;
|
| private Set<Classe> classes;
|
| private Set<Famille> familles;
|
| private Stock stock;
|
| private long version;
|
| public Produit()
| {
| this.stock = new Stock();
| stock.setProduit(this);
| classes = new TreeSet<Classe>();
| familles = new TreeSet<Famille>();
| }
|
| @Version()
| @Column(name="version")
| public long getVersion()
| {
| return version;
| }
|
| public void setVersion(long version)
| {
| this.version = version;
| }
|
| @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch
= FetchType.EAGER)
| @JoinTable(name = "classe_produit",
| joinColumns = { @JoinColumn(name = "produit_id") },
| inverseJoinColumns = { @JoinColumn(name =
"classe_id") })
| public Set<Classe> getClasses()
| {
| return classes;
| }
|
| public void setClasses(Set<Classe> classes)
| {
| this.classes = classes;
| }
|
| @Column(name = "code_produit")
| public String getCodeProduit()
| {
| return codeProduit;
| }
|
| public void setCodeProduit(String codeProduit)
| {
| this.codeProduit = codeProduit;
| }
|
| @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch
= FetchType.EAGER )
| @JoinTable(name = "famille_produit",
| joinColumns = { @JoinColumn(name = "produit_id") },
| inverseJoinColumns = { @JoinColumn(name =
"famille_id") })
| public Set<Famille> getFamilles()
| {
| return familles;
| }
|
| public void setFamilles(Set<Famille> familles)
| {
| this.familles = familles;
| }
|
| @Column(name = "libelle_produit")
| public String getLibelleProduit()
| {
| return libelleProduit;
| }
|
| public void setLibelleProduit(String libelleProduit)
| {
| this.libelleProduit = libelleProduit;
| }
|
| @Id
| @GeneratedValue(strategy = GenerationType.AUTO)
| @Column(name = "produit_id")
| public long getProduitID()
| {
| return produitID;
| }
|
| public void setProduitID(long produitID)
| {
| this.produitID = produitID;
| }
|
| @OneToOne(cascade = {CascadeType.ALL})
| @JoinColumn(name = "stock_id")
| public Stock getStock()
| {
| return stock;
| }
|
| public void setStock(Stock stock)
| {
| this.stock = stock;
| }
|
| public boolean equals(Object obj)
| {
| if(obj == this)
| return true;
| if(!(obj instanceof Produit))
| return false;
| else
| return
this.getCodeProduit().equalsIgnoreCase(((Produit)obj).getCodeProduit());
| }
|
| public int hashCode()
| {
| int result = 17;
| result = 37 * result + this.getCodeProduit().hashCode();
| return result;
| }
|
| public String toString()
| {
| return this.getLibelleProduit();
| }
|
| public int compareTo(Object obj)
| {
| if(!(obj instanceof Produit))
| return -1;
| else
| return
this.getCodeProduit().compareTo(((Produit)obj).getCodeProduit());
| }
|
| }
|
|
|
| import java.io.Serializable;
| import java.util.Collection;
| import java.util.Set;
|
| import javax.persistence.CascadeType;
| import javax.persistence.Column;
| import javax.persistence.Entity;
| import javax.persistence.FetchType;
| import javax.persistence.GeneratedValue;
| import javax.persistence.GenerationType;
| import javax.persistence.Id;
| import javax.persistence.JoinColumn;
| import javax.persistence.JoinTable;
| import javax.persistence.ManyToMany;
| import javax.persistence.Table;
| import javax.persistence.Version;
|
| import com.elina.commercialis.server.stock.produit.Produit;
|
| @Entity
| @Table(name = "famille")
| public class Famille implements Serializable, Comparable
| {
|
| private long familleID;
|
| private String codeFamille;
|
| private String nomFamille;
|
| private String description;
|
| private Set<Produit> produits;
|
| private long version;
|
| @Version()
| @Column(name = "version")
| public long getVersion()
| {
| return version;
| }
|
| public void setVersion(long version)
| {
| this.version = version;
| }
|
| @Column(name = "code_famille")
| public String getCodeFamille()
| {
| return codeFamille;
| }
|
| public void setCodeFamille(String codeFamille)
| {
| this.codeFamille = codeFamille;
| }
|
| @Column(name = "description")
| public String getDescription()
| {
| return description;
| }
|
| public void setDescription(String description)
| {
| this.description = description;
| }
|
| @Id
| @GeneratedValue(strategy = GenerationType.AUTO)
| @Column(name = "famille_id")
| public long getFamilleID()
| {
| return familleID;
| }
|
| public void setFamilleID(long familleID)
| {
| this.familleID = familleID;
| }
|
| @Column(name = "nom_famille")
| public String getNomFamille()
| {
| return nomFamille;
| }
|
| public void setNomFamille(String nomFamille)
| {
| this.nomFamille = nomFamille;
| }
|
| @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch
= FetchType.LAZY, mappedBy="familles" )
| public Set<Produit> getProduits()
| {
| return produits;
| }
|
| public void setProduits(Set<Produit> produits)
| {
| this.produits = produits;
| }
|
| public boolean equals(Object obj)
| {
| if(obj == this)
| return true;
| if(!(obj instanceof Famille))
| return false;
| else
| return
this.getCodeFamille().equalsIgnoreCase(((Famille)obj).getCodeFamille());
| }
|
| public int hashCode()
| {
| return this.getCodeFamille().hashCode();
| }
|
|
| public String toString()
| {
| return this.getNomFamille();
| }
|
| public int compareTo(Object obj)
| {
| if(!(obj instanceof Famille))
| return -1;
| else
| return
this.getNomFamille().compareTo(((Famille)obj).getNomFamille());
| }
| }
|
|
|
| import java.io.Serializable;
| import java.util.Set;
|
| import javax.persistence.CascadeType;
| import javax.persistence.Column;
| import javax.persistence.Entity;
| import javax.persistence.FetchType;
| import javax.persistence.GeneratedValue;
| import javax.persistence.GenerationType;
| import javax.persistence.Id;
| import javax.persistence.ManyToMany;
| import javax.persistence.Table;
| import javax.persistence.Version;
|
| import com.elina.commercialis.server.stock.produit.Produit;
| @Entity
| @Table(name = "classe")
| public class Classe implements Serializable,Comparable
| {
|
| private long classeID;
|
| private String codeClasse;
|
| private String libelleClasse;
|
| private String description;
|
| private Set<Produit> produits;
|
| private long version;
|
| @Version()
| @Column(name="version")
| public long getVersion()
| {
| return version;
| }
|
| public void setVersion(long version)
| {
| this.version = version;
| }
|
|
| @Id
| @GeneratedValue(strategy = GenerationType.AUTO)
| @Column(name = "classe_id")
| public long getClasseID()
| {
| return classeID;
| }
|
| public void setClasseID(long classeID)
| {
| this.classeID = classeID;
| }
|
| @Column(name = "code_classe")
| public String getCodeClasse()
| {
| return codeClasse;
| }
|
| public void setCodeClasse(String codeClasse)
| {
| this.codeClasse = codeClasse;
| }
|
| @Column(name = "description")
| public String getDescription()
| {
| return description;
| }
|
| public void setDescription(String description)
| {
| this.description = description;
| }
|
| @Column(name = "libelle_classe")
| public String getLibelleClasse()
| {
| return libelleClasse;
| }
|
| public void setLibelleClasse(String libelleClasse)
| {
| this.libelleClasse = libelleClasse;
| }
|
| @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch
= FetchType.LAZY, mappedBy="classes" )
| public Set<Produit> getProduits()
| {
| return produits;
| }
|
| public void setProduits(Set<Produit> produits)
| {
| this.produits = produits;
| }
|
| public boolean equals(Object obj)
| {
| if(obj == this)
| return true;
| if(!(obj instanceof Classe))
| return false;
| else
| return
this.getCodeClasse().equalsIgnoreCase(((Classe)obj).getCodeClasse());
| }
|
| public int hashCode()
| {
| return this.getCodeClasse().hashCode();
| }
|
|
| public String toString()
| {
| return this.getLibelleClasse();
| }
|
| public int compareTo(Object obj)
| {
| if(!(obj instanceof Classe))
| return -1;
| else
| return
this.getLibelleClasse().compareTo(((Classe)obj).getLibelleClasse());
| }
| }
|
After a few update of product (adding /removing Classes/Famillies, the system
falls over with the following exception :
|
| at java.awt.EventDispatchThread.run(Unknown Source)
| java.lang.NullPointerException
| at
com.elina.commercialis.server.stock.produit.Produit.hashCode(Produit.java:151)
| at java.util.HashMap.hash(HashMap.java:264)
| at java.util.HashMap.put(HashMap.java:382)
| at java.util.HashSet.add(HashSet.java:194)
| at java.util.AbstractCollection.addAll(AbstractCollection.java:318)
| at
org.hibernate.collection.PersistentSet.endRead(PersistentSet.java:273)
| at
org.hibernate.engine.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:183)
| at
org.hibernate.engine.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:268)
| at
org.hibernate.engine.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:249)
| at org.hibernate.loader.Loader.endCollectionLoad(Loader.java:866)
| at
org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:853)
| at org.hibernate.loader.Loader.doQuery(Loader.java:717)
| at
org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
| at org.hibernate.loader.Loader.loadEntity(Loader.java:1785)
| at
org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:93)
| at
org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:81)
| at
org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:2730)
| at
org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:365)
| at
org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:346)
| at
org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:123)
| at
org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:177)
| at
org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:87)
| at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:891)
| at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:859)
| at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:266)
| at org.hibernate.type.EntityType.resolve(EntityType.java:303)
| at org.hibernate.type.EntityType.nullSafeGet(EntityType.java:217)
| at
org.hibernate.persister.collection.AbstractCollectionPersister.readElement(AbstractCollectionPersister.java:644)
| at
org.hibernate.collection.PersistentSet.readFrom(PersistentSet.java:262)
| at org.hibernate.loader.Loader.readCollectionElement(Loader.java:994)
| at org.hibernate.loader.Loader.readCollectionElements(Loader.java:635)
| at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:580)
| at org.hibernate.loader.Loader.doQuery(Loader.java:689)
| at
org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
| at org.hibernate.loader.Loader.loadEntity(Loader.java:1785)
| at
org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:93)
| at
org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:81)
| at
org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:2730)
| at
org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:365)
| at
org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:346)
| at
org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:123)
| at
org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:177)
| at
org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:87)
| at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:891)
| at org.hibernate.impl.SessionImpl.get(SessionImpl.java:828)
| at
org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:209)
| at
org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:100)
| at
org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:52)
| at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:701)
| at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:685)
| at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:689)
| at
org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:138)
| at
org.jboss.ejb3.entity.InjectedEntityManager.merge(InjectedEntityManager.java:146)
| at
com.elina.commercialis.server.facade.stock.produit.ProduitSessionFacadeBean.modifier(ProduitSessionFacadeBean.java:29)
| at
com.elina.commercialis.server.facade.stock.produit.ProduitSessionFacadeBean.sauver(ProduitSessionFacadeBean.java:23)
| at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
| at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
| at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
| at java.lang.reflect.Method.invoke(Method.java:585)
| at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:109)
| at
org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
| at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
| at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:79)
| at
org.jboss.aspects.tx.TxInterceptor$RequiresNew.invoke(TxInterceptor.java:262)
| at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
| at
org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
| at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
| at
org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:54)
| at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
| at
org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:78)
| at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
| at
org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:47)
| at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
| at
org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
| at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
| at
org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:219)
| at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:107)
| at
org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82)
| at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:660)
| at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:513)
| at
org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:290)
| at
org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:344)
| at
org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:202)
| at
org.jboss.remoting.RemoteClientInvoker.invoke(RemoteClientInvoker.java:163)
| at org.jboss.remoting.Client.invoke(Client.java:258)
| at org.jboss.remoting.Client.invoke(Client.java:221)
| at
org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemoteInterceptor.java:55)
| at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
| at
org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPropagationInterceptor.java:61)
| at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
| at
org.jboss.aspects.security.SecurityClientInterceptor.invoke(SecurityClientInterceptor.java:55)
| at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
| at
org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:65)
| at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
| at
org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:102)
| at $Proxy0.sauver(Unknown Source)
| at
com.elina.commercialis.client.delegate.stock.produit.ProduitDelegate.createProduit(ProduitDelegate.java:21)
| at
com.elina.commercialis.client.gui.screens.stock.produit.ProduitTab.enregistrer(ProduitTab.java:81)
| at
com.elina.commercialis.client.util.gui.screens.CommercialisToolbarBuilder$2.actionPerformed(CommercialisToolbarBuilder.java:80)
| at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
| at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
| at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
| at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
| at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown
Source)
| at java.awt.Component.processMouseEvent(Unknown Source)
| at javax.swing.JComponent.processMouseEvent(Unknown Source)
| at java.awt.Component.processEvent(Unknown Source)
| at java.awt.Container.processEvent(Unknown Source)
| at java.awt.Component.dispatchEventImpl(Unknown Source)
| at java.awt.Container.dispatchEventImpl(Unknown Source)
| at java.awt.Component.dispatchEvent(Unknown Source)
| at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
| at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
| at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
| at java.awt.Container.dispatchEventImpl(Unknown Source)
| at java.awt.Window.dispatchEventImpl(Unknown Source)
| at java.awt.Component.dispatchEvent(Unknown Source)
| at java.awt.EventQueue.dispatchEvent(Unknown Source)
| at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
| at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
| at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
| at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
| at java.awt.EventDispatchThread.run(Unknown Source)
|
I have checked the DB and there are No row with an empty code_produit. As a
matter if fact a NULL constraint is defined on this column.
Using the debugger, it appear that somehow the hasCode method is called with an
Object where codeProduit is null !
Any idea ?
This many to many entity manager problem is really taking the fun out of EJB
3.0 !!!!!!!!!!!!!!!!!!!
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3929928#3929928
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3929928
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
JBoss-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jboss-user