JPA OneToMany and ManyToOne throw: Repeated column in mapping for entity column (should be mapped with insert="false" update="false")
I have three classes one of the names is User and this user has other classes instances. Like this;
public class User{
@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
public List<APost> aPosts;
@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
public List<BPost> bPosts;
}
public class BPost extends Post {
@ManyToOne(fetch=FetchType.LAZY)
public User user;
}
public class APost extends Post {
@ManyToOne(fetch=FetchType.LAZY)
public User user;
}
it's working like this but generates empty tables in DB. Which have to contain foreign keys. When I tried to use mappedBy
and JoinColumn
annotations I got failed. How can I resolve this?
Extra information:
When I changed with;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="id")
public User user;
and
@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="id")
public List<APost> aPosts;
I'm getting
A JPA error occurred (Unable to build EntityManagerFactory): Repeated column in mapping for entity: models.post.APost column: id (should be mapped with insert="false" update="false")
Final Edit: Finally, I was totally wrong about JPA annotations. :( When I change
@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="id")
to
@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
and
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="user_id")
everything works ok. :)
I am not really sure about your question (the meaning of "empty table" etc, or how mappedBy
and JoinColumn
were not working).
I think you were trying to do a bi-directional relationships.
First, you need to decide which side "owns" the relationship. Hibernate is going to setup the relationship base on that side. For example, assume I make the Post
side own the relationship (I am simplifying your example, just to keep things in point), the mapping will look like:
(Wish the syntax is correct. I am writing them just by memory. However the idea should be fine)
public class User{
@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
private List<Post> posts;
}
public class Post {
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="user_id")
private User user;
}
By doing so, the table for Post
will have a column user_id
which store the relationship. Hibernate is getting the relationship by the user
in Post
(Instead of posts
in User
. You will notice the difference if you have Post
's user
but missing User
's posts
).
You have mentioned mappedBy
and JoinColumn
is not working. However, I believe this is in fact the correct way. Please tell if this approach is not working for you, and give us a bit more info on the problem. I believe the problem is due to something else.
Edit:
Just a bit extra information on the use of mappedBy
as it is usually confusing at first. In mappedBy
, we put the "property name" in the opposite side of the bidirectional relationship, not table column name.
You should never use the unidirectional @OneToMany
annotation because:
- It generates inefficient SQL statements
- It creates an extra table which increases the memory footprint of your DB indexes
Now, in your first example, both sides are owning the association, and this is bad.
While the @JoinColumn
would let the @OneToMany
side in charge of the association, it's definitely not the best choice. Therefore, always use the mappedBy
attribute on the @OneToMany
side.
public class User{
@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
public List<APost> aPosts;
@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
public List<BPost> bPosts;
}
public class BPost extends Post {
@ManyToOne(fetch=FetchType.LAZY)
public User user;
}
public class APost extends Post {
@ManyToOne(fetch=FetchType.LAZY)
public User user;
}