Hibernate example 3 – one to one associations

Just put a Hibernate example of the three different ways to create one-to-one associations on github:

https://github.com/hedleyproctor/hibernate-one-to-one

It contains a Customer entity, which has one-to-one associations to a UserProfile, MarketingPreferences and a Wistlist.

  1. Foreign key relationship. Customer has a foreign key to UserProfile.
  2. Shared primary key. The MarketingPreferences entity is set to use the same primary key as the customer, so its primary key is also a foreign key to the customer.
  3. Join table. Customer and wishlist are linked by a join table, appropriate if the association is optional.

The code is built using maven, so you run the tests with:

mvn test

I’ll quickly explain how each type of association is mapped.

The relationship between Customer and UserProfile is a foreign key, which is the default for a one to one association, so you simply need the @OneToOne annotation in the Customer class:

	private UserProfile userProfile;
 
	@OneToOne(cascade = CascadeType.ALL)
	public UserProfile getUserProfile() {
		return userProfile;
	}

You can see I’ve also set a cascade on this mapping, so that if you create a new customer and user profile, the user profile will be saved automatically, but it isn’t related to how the mapping works.

Then, if you want to make the association bidirectional, in the UserProfile class, add a Customer instance variable, but specify that the association is mapped and controlled by the userProfile instance variable in the Customer class. This is the standard set up for bi-directional associations – you must not define the association on both sides, as this would actually create two associations. The code in UserProfile is:

	@OneToOne(mappedBy = "userProfile")
	public Customer getCustomer() {
		return customer;
	}

For the MarketingPreferences, it is set to always get the same value as its primary key as its corresponding Customer instance. Hence the primary key for MarketingPreferences is also a foreign key to the Customer. In the MarketingPreferences class this is mapped as:

	private Long id;
	private Customer customer;
 
	@Id
	public Long getId() {
		return id;
	}
 
	@MapsId
	@OneToOne
	public Customer getCustomer() {
		return customer;
	}

In most classes, the id would be generated by the database, so the @Id annotation would be accompanied by @GeneratedValue. Here, the id must be obtained from the associated Customer class. We have an instance variable of type Customer, and the @MapsId annotation tells Hibernate that the foreign key for it should not be put in a new database column, but instead is to be used as the primary key.

To make this bidirectional, on the Customer side, you must tell Hibernate to use the primary key of MarketingPreferences when it joins the database tables:

	@OneToOne(cascade = CascadeType.ALL)
	@PrimaryKeyJoinColumn
	public MarketingPreferences getMarketingPreferences() {
		return marketingPreferences;
	}

Finally there is the association between Customer and Wishlist, which is mapped by an intermediate join table. This approach is useful for two reasons. Firstly, when the assocation is optional – although you could have a null database foreign key, this isn’t best practice. Secondly, if you want to add properties to the association, the join table gives you a place to put them. The mapping in the Customer class is:

	@OneToOne(cascade = CascadeType.ALL)
	@JoinTable( name = "CUSTOMER_WISHLIST", 
		joinColumns = @JoinColumn( name = "CUSTOMER_ID"),
		inverseJoinColumns = @JoinColumn( name = "WISHLIST_ID"))
	public Wishlist getWishlist() {
		return wishlist;
	}

To make the association bidirectional, add a Customer instance variable to the Wishlist, and specify that the mapping is done by the Customer:

	@OneToOne(mappedBy = "wishlist")
	public Customer getCustomer() {
		return customer;
	}

For more info about one to one associations, check out chapter 8 of the Hibernate docs:
http://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html/ch08.html

This entry was posted in Hibernate, Java and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

501,820 Spambots Blocked by Simple Comments

HTML tags are not allowed.