views:

832

answers:

1

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)
+1  A: 

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)

Aaron Digulla
Well, I do not want a composite key. How do I do the ManyToMany mapping without composite key?
nimcap

related questions