I have a person Entity and two list of persons in it, that i implemented this way (thanks to this post : Hibernate many-to-many association with the same entity) :
#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;
But, with the #ManyToMany annotation the Cascadings (MERGE,DELETE,etc..) doesn't work.
Is there a way to achieve the same mapping but with enabling Cascadings ?
Cascadings do work with many-to-many associations. But most of the time, there shouldn't be any cascade set on a many-to-many association: since a friend is a friend of many persons, you can't, for example, delete all John's friends (Paul and Matt) when you delete John. Indeed, many other people (Jack, Sarah) also have Paul and Matt as friends, and it would thus lead to a constraint violation.
The problem with your code is that the mapping is wrong. You have a single, bidirectional, many-to-many association here, but you mapped it as two unidirectional many-to-many associations, using the same join table.
In a bidirectional association, one side must be the inverse side. If you choose friendOf as the inverse side, it should thus be mapped as
#ManyToMany(mappedBy = "friends")
private List<User> friendOf;
Related
JPA Provider is EclipseLink. Having the following entities:
#Entity
class Symptom {
#ManyToMany(mappedBy = "symptoms")
private Set<Disorder> disorders;
}
#Entity
class Disorder {
#ManyToMany
#JoinTable(name = "disorder_symptoms")
private Set<Symptom> symptoms;
}
One symptom can be found on many disorders and many disorders can have many symptoms. Symptom is defined as the inverse (non-owning) side of the relationship, but this being a bidirectional relationship, it shouldn't matter.
When i add a new symptom to Disorder, database table disorder_symptoms is updated as expected. But when i add a disorder to Symptom, the table is not populated. Tried with cascade attribute set for either side, still no result.
Is there something wrong i'm doing here?
I was thinking that I understand the relations. But now.. Im not sure. I have a problem to add correct annotations.
I have classes Members and Relations.
In Relations
private GT_Member Mother;
private GT_Member Father;
private List<GT_Member> children;
One Member can be in several Relations as Mother or Father (reference to his sex) but he can be only in One relation as child.
I thought annotate Mother and Father as #OneToMany.
But I'm not sure if I can annotate List as #OneToOne ??
This seems like a problem in modeling the correct entity-relationship model for your database schema and visualizing your ORM (Object Relationship Model).
Rather than starting with classes Members and Relations, please first see what are the dominant data-entities in your system. And how would they be related to each other.
Personally I do not think Relation would be a good JPA entity.
Member looks more like a good entity and could embody the relations
Assuming one Father and one Mother, One to Many seems wrong but as a father or mother can have many children, the correct annotation should be #ManyToOne.
Children is definitely OneToMany, and yes you can annotate the List children as #OneToMany.
Member could have the following properties:
#Entity
public class Member implements Serializable{
#ManyToOne
private Member mother;
#ManyToOne
private Member father;
#OnetoMany
private List<Member> children;
}
This solves both your use cases and in this simple example Relation class is not needed.
hope this helps.
Employment of Relation entity is because I want to save information about status of relation. Donc I will store information about all married etc. Entity relation has other fields like type (neutral, married, fiance etc...).
I am trying to understand what would be the better way to design 2 entities which has many-to-many relationship? In database there will be a connecting table between these two entities. But do i have to follow the same approach while creating my entities?
For example: User to User group
A user may belong to many group and a group may contain many user.
In relational database I will have 3 table like User, User2Group, Group
So when I am creating my JPA entities, should I have 3 entities for 3 table or just 2 entities by providing the proper annotation(#ManytoMany).
Since I am new to JPA, I am trying to understand good and bad side from following point of view:
Performance
Code maintenance
Thanks, you input will be greatly appreciated.
No, you don't need to map the join table as an entity. Just use the ManyToMany annotation:
public class User {
...
#ManyToMany
private Set<Group> groups;
}
public class Group {
...
#ManyToMany(mappedBy = "groups")
private Set<User> users;
}
You would only need to map the join table as an entity if it was not a pure join table, i.e. if it had additional information like, for example, the date when the user entered in the group.
The mapping has little incidence on the performance. What is important is how you use and query the entities, and how the database is designed (indices, etc.)
I have a m:n relationship book - borrow - user, the borrow is the join table.
The tables are given (can not be changed):
on one side they are used by jdbc app as well.
on the other side i would like to use them via jpa
book(book_id) - borrow(book_id,used_id) - user(user_id)
used jpa annotations:
User:
#OneToMany(targetEntity=BorrowEntity.class, mappedBy="user")
#JoinColumn(name="USER_ID", referencedColumnName="USER_ID")
private List<BorrowEntity>borrowings;
Book:
#OneToMany(targetEntity=BorrowEntity.class, mappedBy="book")
#JoinColumn(name="BOOK_ID", referencedColumnName="BOOK_ID")
private List<BorrowEntity>borrowings;
My problem is that by the settings above it adds some extra (undesired) fields to the borrow table:
'user_USER_ID' and 'book_BOOK_ID'
How can I configure the jpa annotations to keep just Borrow:user_id,book_id which is enough the many to one ?
Take a look at the picture which tells more:
First of all, since the borrow table is a pure join table, you don't need to map it at all. All you need is a ManyToMany association using this borrow table as JoinTable.
#ManyToMany
#JoinTable(name = "borrow",
joinColumns = #JoinColumn(name = "USER_ID"),
inverseJoinColumns = #JoinColumn(name = "BOOK_ID"))
private List<Book> borrowedBooks;
...
#ManyToMany(mappedBy = "borrowedBooks")
private List<User> borrowingUsers;
If you really want to map the join table as an entity, then it should contain two ManyToOne associations (one for each foreign key). So the following is wrong:
#OneToMany(targetEntity=BorrowEntity.class, mappedBy="user")
#JoinColumn(name="USER_ID", referencedColumnName="USER_ID")
private List<BorrowEntity>borrowings;
Indeed, mappedBy means: this association is the inverse side of the bidirectional OneToMany/ManyToOne association, which is already mapped by the field user in the BorrowEntity entity. Please see the annotations on this field to know how to map the association.
So the #JoinColumn doesn't make sense. It's in contradiction with mappedBy. You just need the following:
#OneToMany(mappedBy="user")
private List<BorrowEntity>borrowings;
The targetEntity is also superfluous, since it's a List<BorrowEntity>: JPA can infer the target entity from the generic type of the list.
I have users and each user has several roles. Roles and users are in many-to-many relationship. But the role is just a name. I've got stuck in this phase:
#ManyToMany
#JoinTable(name="users2roles")
private Collection<String> roles;
There is missing the name of target table. I was searching on Internet, but nothing have found. I don't wannt to create special entity class to wrap one string value. Is there some another way, isn't?
Is there any way to make it work or makes JPA me create a new entity?
A Collection of Strings isn't relating one object to another so cannot be a #OneToMany or #ManyToMany - ought to be #ElementCollection. It's a collection of Strings, nothing more. Yes, it can be stored in a join table, but using #CollectionTable.