persistence@glassfish.java.net

Re: how to map Self-referencing table ManyToMany relationship

From: Christopher Delahunt <christopher.delahunt_at_oracle.com>
Date: Thu, 12 Aug 2010 13:06:38 -0400

The relationship is unidirectional, otherwise there would be no way to
add a new reference to the list. Without a direction being specified,
there would be no consistency to which 'side' of the relation table a
node gets added to, and it will lead to duplicates when being read in.
And in most relationships, nodeId1->nodeId2 does not imply that nodeId2
references nodeId1. Think of a person having a collection of children
(who are legally also persons). You would not want a parent in its own
list of children.

In JPA, when you want to access the relationships in the other direction
you need to create a mapping for it. Since you wish to use the same
relationship table and just represent the NodeId2->nodeId1 relationship,
create a new collection and mark it with
@ManyToMany(mappedBy="linkedNodes").

Best Regards,
Chris




On 12/08/2010 11:26 AM, reljicb wrote:
> Hi!
>
> I'm not very experienced with persistence, so if anybody of persistence
> experts have idea how to solve this, please assist.
>
> I have database that models bi-directional graphs.
> There is a Node table:
>
> Table node
> ==========
> id INT
> name VARCHAR
> nodeType INT
>
> Any Node can be linked to many other nodes. I use Link table as association
> table to link them.
>
> Table link
> ==========
> nodeId1 INT
> nodeId2 INT
>
> When I generate persistence entities (NetBeans), I get a class member
> "linkedNodes" defined as following:
>
> @JoinTable(name = "link",
> joinColumns = {_at_JoinColumn(name = "nodeId1",
> referencedColumnName = "id", nullable = false)},
> verseJoinColumns = {_at_JoinColumn(name = "nodeId2",
> referencedColumnName = "id", nullable = false)})
> @ManyToMany
> private Collection<Node> linkedNodes;
>
> The problem is that this JPA mapping behaves as if the graph is
> unidirectional - linkedNodes collection contains ONLY those nodes which are
> linked to this one in nodeId1->nodeId2 direction manner. In other words,
> table Link is queried for only those records where Id of the current node is
> in nodeId1 filed, and Ids of other (linked) nodes are in nodeId2 column, and
> not vice-verse.
>
> This perfectly makes seanse when ManyToMany relationship is defined between
> two different tables.
>
> But here I want to obtain all the nodes which are linked to the current one.
> In other words, when Id of current node is in EITHER nodeId1 OR nodeId2
> column of the Link table.
>
> Thanks in advance.
> Your help is very much appreciated.
>
> Bojan
>
>