Hibernate

ID #1001

How does one handle a foreign key in a composite primary key?

This issue is covered briefly in "Java Persistence with Hibernate" (p. 328). To summarize the issue:


Imagine you have three classes: Book, Author, and BookAuthor.

The BookAuthor class is of course a join table that maps the many-to-many relationship between Book and Author. Generally speaking, Hibernate would encourage you to have a synthetic primary key for BookAuthor, but it's common to have a composite primary key made of the two foreign keys.

So your BookAuthor class might end up looking like this:

 

@Entity
public class BookAuthor {

	@EmbeddedId
	private BookAuthorPK id;

	@ManyToOne(fetch=FetchType.LAZY)
	@JoinColumn(name="bookId", nullable=false, insertable=false, updatable=false)
	private Book book;

	@ManyToOne(fetch=FetchType.LAZY)
	@JoinColumn(name="authorId", nullable=false, insertable=false, updatable=false)
	private Author author;
  etc...

and the primary key class:

@Embeddable
public class BookAuthorPK {
    @Column(name="bookId", nullable=false)
    private String bookId;

    @Column(name="authorId", nullable=false)
    private String authorId;
    etc...

The danger here is that there seems to be two ways of setting a BookAuthor's author (or book):

- you can change the BookAuthorPK to point to a different author, or

- you can set the BookAuthor's relationship using setAuthor

Note that the second approach will not be persistent, since the relationship is marked as updatable=false.

So the crux of the problem is that it is possible to set one value in the BookAuthorPK, while the relationship itself does not reflect this (at least not until the object is refreshed from the database).

This is a common issue, and the best way to avoid it is to code the beans to avoid the problem. For instance:

@Entity
public class BookAuthor {

    ...
    public void setAuthor(Author author) {
        this.author = author;
        this.id.authorId = author.getId();
    }

You might also make the primary key object non-updatable so that there is only one way to set the relationship. There are various ways of doing this, using protected methods, constructors, etc...

Tags: -

Related entries:

Last update: 2011-09-28 06:46
Author: Max Tardiveau
Revision: 1.0

Digg it! Share on Facebook Print this record Send FAQ to a friend Show this as PDF file
Propose a translation for Propose a translation for
Please rate this FAQ:

Average rating: 0 (0 Votes)

completely useless 1 2 3 4 5 most valuable

You cannot comment on this entry