M:N relationship in JPA (wrapping given tables)
Asked Answered
R

1

5

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:

book borrowing

Recital answered 21/7, 2012 at 21:38 Comment(0)
P
7

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.

Phuongphycology answered 22/7, 2012 at 8:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.