ManyToMany in Hibernate without composite keys
-
06-09-2019 - |
Question
I am dealing with legacy database. And I am writing unit test using pojos & hibernate & HSQLDB. And I am getting the following error:
17:09:03,946 ERROR SchemaExport:349 - Attempt to define a second primary key in statement
Let's say I have Post
and Tag
entities (and of course their tables posts
and tags
). And there is another table to define many-to-many between Post
and Tag
called post_tags
.
Because post_tags
contains some extra information about the relation, like active
and deleted
columns. I created another Entity called PostTag
to handle this.
To describe my problem here are the pseudo classes:
@Entity
@Table(name="post_tags")
public class PostTag {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@ManyToOne
private Post post;
@ManyToOne
private Tag tag;
// setters and getters
}
@Entity
@Table(name = "tags")
public class Tag {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@ManyToMany(mappedBy = "tags",cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<Post> posts;
// setters and getters
}
@Entity
@Table(name = "posts")
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@ManyToMany
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
@JoinTable(name = "post_tags", joinColumns = { @JoinColumn(name = "post_id") }, inverseJoinColumns = { @JoinColumn(name = "tag_id") })
private Set<Tag> tags;
// setters and getters
}
When I look at the statement that generates the error it seems Hibernate is trying to make a composite key using PRIMARY KEY (post_id, tag_id)
, and also it tries to make post_id
identity
.
Can anyone help me to fix my problem?
UPDATE:
Because I am dealing with a legacy database this was just an example to demonstrate the problem. But I will try to translate the actual statement according to the example (PS: It is not ALTER TABLE
it is a CREATE TABLE
):
create table post_tags (id integer not null, post integer, tag integer, post_id integer generated by default as identity (start with 1), tag_id integer not null, primary key (post_id, tag_id)
Solution
The problem is the @Id in the class PostTag
: It tells hibernate that you want a generated identity colum. At the same time, you're saying "I want a composite key" with the mapping of the tags
field in the class Posts
.
Which one do you want? Hibernate can't tell.
There is a very good example on page 304 in the book "Java Persistence with Hibernate". It's on Google books.
If you don't want the composite key, then you must treat the link table as real objects and use PostTag
in the class Posts
(i.e. Set<PostTag> postTags
instead of Set<Tag> tags
)