I will open a JIRA report with the details and a small test case.
Patrick Linskey-2 wrote: > > Pinaki, > > Can you describe the failure in id creation in a bit more detail? I've > been working on the enhancer recently, so I might be able to dive in > and fix it at some point here. > > -Patrick > > On 7/23/07, Pinaki Poddar <[EMAIL PROTECTED]> wrote: >> >> Self-recursive Entity relation as part of the compound key will continue >> to >> throw SatckOverflow exception with current implementation. I was only >> partially successful in plugging that error by changing OpenJPA >> implementation. Because even if the recursive loop is terminated while >> resolving metadata -- OpenJPA enhanced code does not fully account for >> self-recursive composite keys. Hence the test fails later within enhanced >> code to create an application identity. Making changes to enhanced code >> has >> a more sever impact across the board. >> >> At this point, a tree-structured domain model has to live with simple >> keys >> -- imo. >> >> >> >> CASERO Jaime wrote: >> > >> > After changing the OwnerId class definition as you suggested. >> > The same exception is thrown again: >> > >> > java.lang.StackOverflowError >> > at >> > >> org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepositor >> > y.java:277) >> > at >> > >> org.apache.openjpa.meta.MetaDataRepository.resolveMeta(MetaDataRepositor >> > y.java:528) >> > at >> > >> org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.ja >> > va:488) >> > at >> > >> org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepositor >> > y.java:290) >> > at >> > >> org.apache.openjpa.meta.MetaDataRepository.resolveMeta(MetaDataRepositor >> > y.java:557) >> > at >> > >> org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.ja >> > va:488) >> > ) >> > >> > Any ideas? >> > >> > I'm worry about the "equals" and "hascode" methods overridings >> > of both the Owner and OwnerId (they have a very recursive behavior). >> > Could be this issue affecting the metadata resolving?. I guess "equals" >> > and "hasCode" are only important in runtime. >> > >> > -----Original Message----- >> > From: Pinaki Poddar [mailto:[EMAIL PROTECTED] >> > Sent: Friday, July 20, 2007 10:05 PM >> > To: [email protected] >> > Subject: Re: Mapping tree structures or self-referencing foreign-Keys >> > >> > >> > 1. Owner has a compound key. The key is comprised of two fields: >> > @Id protected String label; >> > @Id protected Owner owner; >> > >> > 2. Owner says that its compound key class is represented by >> > OwnerId.class >> > @IdClass(com.covansys.routingengine.ifc.jpa.OwnerId.class) >> > public class Owner >> > >> > 3. The rule to define the Idclass OwnerId is >> > a) it must declare all the key fields of Owner >> > and you declared 'label' and 'owner' >> > b) the type of the Idclass' fields must be the same as the original >> > fields >> > *except* for relation field. >> > for relation field R, the type of Idclass' field must be the R's >> > identity >> > class type. >> > Here for field 'owner' is a relation field i.e. R=Owner. Id type of >> R >> > is >> > OwnerId. So OwnerId.owner should be of type OwnerId. Resulting into >> > public class OwnerId { >> > public String label; >> > public OwnerId owner; >> > >> > ====================================================================== >> > >> > I do not know the details of your domain model that requires such >> > identity >> > scheme. I would suggest that design a simpler Tree structure like this: >> > >> > @Entity >> > public class Node { >> > @Id >> > private long; >> > @ManyToOne >> > private Node parent; >> > @OneToMany(mappedBy="parent", cascade=CascadeType.ALL) >> > private List<Node> children; >> > } >> > >> > >> > >> > >> > >> > CASERO Jaime wrote: >> >> >> >> Hi all, >> >> >> >> >> >> >> >> I'm trying to persist a tree structure. Here class A >> >> references several A's (as his children -> OneToMany), and one A(p) >> > (as >> >> his parent -> ManyToOne). When JPA is parsing my metadata a >> >> "StackOverflowError" exception is thrown. Seems to be the typical >> >> recursive problem because of the self-referencing foreign key (=a >> >> foreign key to the same table) created. >> >> >> >> >> >> >> >> I haven't seend any referente in the manual to this >> >> scenario. >> >> >> >> >> >> >> >> Has anyone try this before? Is this feature supported by >> >> openJPA/JPA? Should i try one of the standard sql approches >> > ("Adjacency >> >> List Model", "The Path Enumeration Model", "Nested Set Model of >> >> Hierarchies"..), or is completely unsupported? >> >> >> >> >> >> >> >> Thanks in advance >> >> >> >> >> >> >> >> >> >> >> >> Here is the class, and its corresponding Id class: >> >> >> >> >> >> >> >> /////Owner/////// >> >> >> >> package com.covansys.routingengine.functionalcore; >> >> >> >> >> >> >> >> import javax.persistence.*; >> >> >> >> >> >> >> >> import org.apache.openjpa.persistence.ElementDependent; >> >> >> >> >> >> >> >> import com.covansys.routingengine.ifc.jpa.ScreeningElementId; >> >> >> >> >> >> >> >> import java.util.*; >> >> >> >> >> >> >> >> @Entity >> >> >> >> @IdClass(com.covansys.routingengine.ifc.jpa.OwnerId.class) >> >> >> >> public class Owner extends OwnerEntity implements Comparable >> >> >> >> { >> >> >> >> >> >> >> >> @Id >> >> >> >> protected String label; >> >> >> >> >> >> >> >> @Id >> >> >> >> @ManyToOne >> >> >> >> protected Owner owner; >> >> >> >> /** >> >> >> >> * <p> >> >> >> >> * This function returns the value of the owner member >> >> >> >> * </p> >> >> >> >> * @return owner, Owner object which contains the owner >> >> member value >> >> >> >> */ >> >> >> >> public Owner getOwner() >> >> >> >> { >> >> >> >> return owner; >> >> >> >> } >> >> >> >> >> >> >> >> >> >> >> >> /** >> >> >> >> * <p> >> >> >> >> * This function sets the owner value to the value of the >> >> owner passed >> >> >> >> * as argument. If the value of the targetOwner is null >> > then >> >> it sets its >> >> >> >> * value to the same owner. >> >> >> >> * </p> >> >> >> >> * @param o Owner object to be set as owner >> >> >> >> */ >> >> >> >> public void setOwner(Owner o) >> >> >> >> { >> >> >> >> owner = o; >> >> >> >> } >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> /** >> >> >> >> * <p> >> >> >> >> * This function returns the value of the label member >> >> >> >> * </p> >> >> >> >> * @return label, String which contains the label member >> >> value >> >> >> >> */ >> >> >> >> public String getLabel() >> >> >> >> { >> >> >> >> return label; >> >> >> >> } >> >> >> >> >> >> >> >> >> >> >> >> /** >> >> >> >> * <p> >> >> >> >> * This function sets the value of the label member to the >> >> value >> >> >> >> * of the String passed as argument >> >> >> >> * </p> >> >> >> >> * @param l String to be set as label >> >> >> >> */ >> >> >> >> public void setLabel(String l) >> >> >> >> { >> >> >> >> label = l; >> >> >> >> } >> >> >> >> >> >> >> >> @ElementDependent >> >> >> >> @OneToMany(mappedBy="owner", cascade={CascadeType.ALL}) >> >> >> >> private Set<Owner> children; >> >> >> >> >> >> >> >> >> >> >> >> @Basic >> >> >> >> private String tag; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> public Owner() >> >> >> >> { >> >> >> >> children = new HashSet<Owner>(); >> >> >> >> } >> >> >> >> >> >> >> >> public void setOwnerId(long id) >> >> >> >> { >> >> >> >> //ownerId= id; >> >> >> >> } >> >> >> >> >> >> >> >> public long getOwnerId() >> >> >> >> { >> >> >> >> //return ownerId; >> >> >> >> return 0; >> >> >> >> } >> >> >> >> >> >> >> >> public int compareTo(Object o) >> >> >> >> { >> >> >> >> if (o instanceof Owner) >> >> >> >> { >> >> >> >> Owner owner = (Owner)o; >> >> >> >> return >> >> getLabel().compareTo(owner.getLabel()); >> >> >> >> } else { >> >> >> >> //put behind >> >> >> >> return 1; >> >> >> >> } >> >> >> >> } >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> /*public int hashCode() { >> >> >> >> return ((label == null) ? 0 : label.hashCode()) >> >> >> >> ^ ((owner == null) ? 0 : owner.hashCode()); >> >> >> >> } */ >> >> >> >> >> >> >> >> public boolean equals(Object o) >> >> >> >> { >> >> >> >> if (this == o) return true; >> >> >> >> if (o instanceof Owner) >> >> >> >> { >> >> >> >> Owner owner = (Owner)o; >> >> >> >> //return this.getOwner() == >> >> owner.getOwner() && getLabel().equals(owner.getLabel()); >> >> >> >> return >> >> getLabel().equals(owner.getLabel()); >> >> >> >> } else { >> >> >> >> return false; >> >> >> >> } >> >> >> >> } >> >> >> >> >> >> >> >> public boolean isChild(Owner o) >> >> >> >> { >> >> >> >> if (o == null ) >> >> >> >> { >> >> >> >> return false; >> >> >> >> } else { >> >> >> >> if (equals(o)) { >> >> >> >> return true; >> >> >> >> } else { >> >> >> >> boolean found = false; >> >> >> >> Iterator<Owner> it = >> >> children.iterator(); >> >> >> >> Owner child = null; >> >> >> >> while(it.hasNext() && >> >> !found) { >> >> >> >> child = >> >> it.next(); >> >> >> >> found = >> >> child.isChild(o); >> >> >> >> } >> >> >> >> return found; >> >> >> >> } >> >> >> >> } >> >> >> >> } >> >> >> >> >> >> >> >> >> >> >> >> public void setTag(String t) >> >> >> >> { >> >> >> >> tag = t; >> >> >> >> } >> >> >> >> >> >> >> >> public String getTag() >> >> >> >> { >> >> >> >> return tag; >> >> >> >> } >> >> >> >> >> >> >> >> public void addChild(Owner o) >> >> >> >> { >> >> >> >> children.add(o); >> >> >> >> o.setOwner(this); >> >> >> >> } >> >> >> >> public void removeChild(Owner o) >> >> >> >> { >> >> >> >> children.remove(o); >> >> >> >> } >> >> >> >> public void removeAllChildren() >> >> >> >> { >> >> >> >> for (int i = 0 ; i < children.size(); i ++) >> >> >> >> children.remove(i); >> >> >> >> } >> >> >> >> >> >> >> >> public Collection<Owner> getChildren() >> >> >> >> { >> >> >> >> return children; >> >> >> >> } >> >> >> >> >> >> >> >> >> >> >> >> public List<Owner> getAllChildren() >> >> >> >> { >> >> >> >> List<Owner> allChildren = new Vector<Owner>(); >> >> >> >> for(Owner oAux : children) >> >> >> >> { >> >> >> >> >> >> allChildren.addAll(oAux.getAllChildren()); >> >> >> >> } >> >> >> >> return allChildren; >> >> >> >> } >> >> >> >> >> >> >> >> public Owner searchChild(String label) throws >> > OwnerNotFound >> >> >> >> { >> >> >> >> Owner oAux = new Owner(); >> >> >> >> oAux.setLabel(label); >> >> >> >> return searchChild(oAux); >> >> >> >> } >> >> >> >> >> >> >> >> public Owner searchChildByTag(String t) throws >> > OwnerNotFound >> >> >> >> { >> >> >> >> if (t == null ) >> >> >> >> { >> >> >> >> throw new OwnerNotFound(); >> >> >> >> } else { >> >> >> >> if (t.equals(this.tag)) >> >> >> >> { >> >> >> >> return this; >> >> >> >> } else { >> >> >> >> boolean found = false; >> >> >> >> Iterator<Owner> it = >> >> children.iterator(); >> >> >> >> Owner child = null; >> >> >> >> Owner oAux = null; >> >> >> >> while(it.hasNext() && >> >> !found) >> >> >> >> { >> >> >> >> try >> >> >> >> { >> >> >> >> >> >> child = it.next(); >> >> >> >> >> >> oAux = child.searchChildByTag(t); >> >> >> >> >> >> found = true; >> >> >> >> } catch >> >> (Exception e) { >> >> >> >> >> > >> >> >> >> } >> >> >> >> } >> >> >> >> if (found) >> >> >> >> { >> >> >> >> return >> > oAux; >> >> >> >> } else { >> >> >> >> throw new >> >> OwnerNotFound(); >> >> >> >> } >> >> >> >> } >> >> >> >> } >> >> >> >> } >> >> >> >> >> >> >> >> public Owner searchChild(Owner o) throws OwnerNotFound >> >> >> >> { >> >> >> >> if (o == null ) >> >> >> >> { >> >> >> >> throw new OwnerNotFound(); >> >> >> >> } else { >> >> >> >> if (equals(o)) >> >> >> >> { >> >> >> >> return this; >> >> >> >> } else { >> >> >> >> boolean found = false; >> >> >> >> Iterator<Owner> it = >> >> children.iterator(); >> >> >> >> Owner child = null; >> >> >> >> Owner oAux = null; >> >> >> >> while(it.hasNext() && >> >> !found) >> >> >> >> { >> >> >> >> try >> >> >> >> { >> >> >> >> >> >> child = it.next(); >> >> >> >> >> >> oAux = child.searchChild(o); >> >> >> >> >> >> found = true; >> >> >> >> } catch >> >> (Exception e) { >> >> >> >> >> >> //this child don't have the owner, try with the next >> >> >> >> } >> >> >> >> } >> >> >> >> if (found) >> >> >> >> { >> >> >> >> return >> > oAux; >> >> >> >> } else { >> >> >> >> throw new >> >> OwnerNotFound(); >> >> >> >> } >> >> >> >> } >> >> >> >> } >> >> >> >> } >> >> >> >> >> >> >> >> } >> >> >> >> >> >> >> >> ////////end owner/////// >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> //////////OwnerId////////// >> >> >> >> package com.covansys.routingengine.ifc.jpa; >> >> >> >> >> >> >> >> import java.util.List; >> >> >> >> >> >> >> >> import com.covansys.routingengine.functionalcore.Owner; >> >> >> >> >> >> >> >> >> >> >> >> public class OwnerId >> >> >> >> { >> >> >> >> public String label; >> >> >> >> public String owner; >> >> >> >> >> >> >> >> public boolean equals(Object other) { >> >> >> >> if (other == this) >> >> >> >> return true; >> >> >> >> if (!(other instanceof OwnerId)) >> >> >> >> return false; >> >> >> >> >> >> >> >> OwnerId mi = (OwnerId) other; >> >> >> >> return (label == mi.label >> >> >> >> || (label != null && label.equals(mi.label))) >> >> >> >> && (owner == mi.owner >> >> >> >> || (owner != null && owner.equals(mi.owner))); >> >> >> >> } >> >> >> >> public int hashCode() { >> >> >> >> return ((label == null) ? 0 : label.hashCode()) >> >> >> >> ^ ((owner == null) ? 0 : owner.hashCode()); >> >> >> >> } >> >> >> >> >> >> >> >> >> >> >> >> } >> >> >> >> /////////end ownerid///////// >> >> >> >> Confidentiality Statement: >> >> >> >> This message is intended only for the individual or entity to which it >> > is >> >> addressed. It may contain privileged, confidential information which >> > is >> >> exempt from disclosure under applicable laws. If you are not the >> > intended >> >> recipient, please note that you are strictly prohibited from >> > disseminating >> >> or distributing this information (other than to the intended >> > recipient) or >> >> copying this information. If you have received this communication in >> >> error, please notify us immediately by return email. >> >> ----------------------------- >> >> >> >> >> > >> > -- >> > View this message in context: >> > >> http://www.nabble.com/Mapping-tree-structures-or-self-referencing-foreig >> > n-Keys-tf4117022.html#a11715126 >> > Sent from the OpenJPA Users mailing list archive at Nabble.com. >> > >> > Confidentiality Statement: >> > >> > This message is intended only for the individual or entity to which it >> is >> > addressed. It may contain privileged, confidential information which is >> > exempt from disclosure under applicable laws. If you are not the >> intended >> > recipient, please note that you are strictly prohibited from >> disseminating >> > or distributing this information (other than to the intended recipient) >> or >> > copying this information. If you have received this communication in >> > error, please notify us immediately by return email. >> > ----------------------------- >> > >> > >> >> -- >> View this message in context: >> http://www.nabble.com/Mapping-tree-structures-or-self-referencing-foreign-Keys-tf4117022.html#a11748494 >> Sent from the OpenJPA Users mailing list archive at Nabble.com. >> >> > > > -- > Patrick Linskey > 202 669 5907 > > -- View this message in context: http://www.nabble.com/Mapping-tree-structures-or-self-referencing-foreign-Keys-tf4117022.html#a11752278 Sent from the OpenJPA Users mailing list archive at Nabble.com.
