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-foreign-Keys-tf4117022.html#a11715126
Sent from the OpenJPA Users mailing list archive at Nabble.com.