0

Supposing I have a many-to-many relationship with an attribute. I want to substitute this with two one-to-many relationships. If I configure the keys, I get a strange warning, that the primary key has an invalid number of attributes.

Here is what I want to have:

User <1:N> Notification <N:1> Thread

You should note, that I need notification to have a composite key constisting of user_id and thread_id.

That is what I've tried:

@Entity
public class Notification implements Serializable {

    @EmbeddedId
    @AttributeOverrides( {
        @AttributeOverride(name = "user_id", column = @Column(nullable = false)),
        @AttributeOverride(name = "thread_id", column = @Column(nullable =false))
    })
    private NotificationPK id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "user_id", insertable = false, updatable = false)
    private User user;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "thread_id", insertable = false, updatable = false)
    private Thread thread;    
}   

On the Thread class it looks like this:

    @OneToMany(fetch=FetchType.LAZY)
    @JoinTable(
        name="notifications",
        joinColumns=@JoinColumn(name="thread_id")
    )
    private Set<Notification> notifications = new HashSet<Notification>();

Using NotificationPK as follows:

@Embeddable
public class NotificationPK implements Serializable {

    Long user_id;
    Long thread_id;
}

However, as soon as I startup, I get the following exception:

 Caused by: org.hibernate.MappingException: 
     Foreign key (FK4BD694E87364C017:notifications 
        [notifications_thread_id,notifications_user_id])) 
     must have same number of columns as the referenced 
     primary key (notifications 
        [thread_id,notifications_thread_id,notifications_user_id])

What am I doing wrong? Why does he expects this to be part of the primary key?

Chris
  • 8,031
  • 10
  • 41
  • 67
  • Why do you "need notification to have a composite key"? Why not change `Notification` to use an auto-generated UID, and then have the 2 foreign key fields being non-null columns in `Notification`? Also, your on-to-many in Thread should use the 'mappedBy' to give the collection. – DuncanKinnear Sep 17 '13 at 23:15
  • I think the answer is similar to the answer I gave for [this question][1]. [1]: http://stackoverflow.com/questions/18205248/jpa-embeddedid-how-to-update-part-of-a-composite-primary-key – DuncanKinnear Oct 08 '13 at 02:13

1 Answers1

0

OK, my first attempt at an answer was aparantly too trivial!

What you need is a UID primary key for Notification which is un-related to the foreign keys which make up the 'join'.

See my answer to this question for a more concrete example.

Community
  • 1
  • 1
DuncanKinnear
  • 4,563
  • 2
  • 34
  • 65