views:

688

answers:

1

Another Hibernate question... :P

Using Hibernate's Annotations framework, I have a User entity. Each User can have a collection of friends: a Collection of other Users. However, I have not been able to figure out how to create a Many-to-Many association within the User class consisting of a list of Users (using a user-friends intermediate table).

Here's the User class and its annotations:

@Entity
@Table(name="tbl_users")
public class User {

    @Id
    @GeneratedValue
    @Column(name="uid")
    private Integer uid;

    ...

    @ManyToMany(
            cascade={CascadeType.PERSIST, CascadeType.MERGE},
            targetEntity=org.beans.User.class
    )
    @JoinTable(
            name="tbl_friends",
            joinColumns=@JoinColumn(name="personId"),
            inverseJoinColumns=@JoinColumn(name="friendId")
    )
    private List<User> friends;
}

The user-friend mapping table has only two columns, both of which are foreign keys to the uid column of the tbl_users table. The two columns are personId (which should map to the current user), and friendId (which specifies the id of the current user's friend).

The problem is, the "friends" field keeps coming out null, even though I've pre-populated the friends table such that all the users in the system are friends with all the other users. I've even tried switching the relationship to @OneToMany, and it still comes out null (though the Hibernate debug output shows a SELECT * FROM tbl_friends WHERE personId = ? AND friendId = ? query, but nothing else).

Any ideas as to how to populate this list? Thank you!

+2  A: 

@ManyToMany to self is rather confusing because the way you'd normally model this differs from the "Hibernate" way. Your problem is you're missing another collection.

Think of it this way - if you're mapping "author" / "book" as many-to-many, you need "authors" collection on Book and "books" collection on Author. In this case, your "User" entity represents both ends of a relationship; so you need "my friends" and "friend of" collections:

@ManyToMany
@JoinTable(name="tbl_friends",
 joinColumns=@JoinColumn(name="personId"),
 inverseJoinColumns=@JoinColumn(name="friendId")
)
private List<User> friends;

@ManyToMany
@JoinTable(name="tbl_friends",
 joinColumns=@JoinColumn(name="friendId"),
 inverseJoinColumns=@JoinColumn(name="personId")
)
private List<User> friendOf;

You can still use the same association table, but note that join / inverseJon columns are swapped on collections.

The "friends" and "friendOf" collections may or may not match (depending on whether your "friendship" is always mutual) and you don't have to expose them this way in your API, of course, but that's the way to map it in Hibernate.

ChssPly76
I was hoping you'd come to my rescue for the third time :) It worked perfectly, and your explanation clears up my understanding of E-R significantly. Thank you very much, once again! :)
Magsol