Archive for the ‘one-to-one’ Tag
Hibernate One-to-One Mapping using Annotations
In an earlier post I had written about getting your development environment setup to start using Hibernate. I had talked about generating a schema, and now it makes sense to proceed to the next logical step, which is persisting data.
As usual, all the code discussed in this post is available at the Google Code Project – DalalStreet.
The objective of this post is to successfully persist a heirarchy of objects using Hibernate. The model consists of a Customer entity, this Customer entity contains an Address entity and a ContactInformation entity. The Address or ContactInformation entity cannot exist independently without a Customer – or in other words – Customer has a one-to-one relationship with Address and ContactInformation.
Hibernate documentation along with a couple of blogs (1, 2) provide insufficient information on how to model one-to-one relationships in Hibernate.
Unfortunately modeling one-to-one relationships in Hibernate is non-trivial and the correct way to model is illustrated in the following code snippets.
Source code for “Customer” entity :
@Entity
@Table(name = "entity_customer")
public class Customer
{
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column (name = "customer_id")
private Long id = null;
@Column(name = "first_name")
private String firstName = null;
@Column(name = "middle_name")
private String middleName = null;
@Column(name = "last_name")
private String lastName = null;
@Column(name = "salutation")
private String salutation = null;
@Column(name = "account_number")
private String accountNumber = null;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn (name = "customer_id")
private Address address = null;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn (name = "customer_id")
private ContactInformation contactInfo = null;
Source code for “Address” entity :
@Entity
@Table(name = "entity_address")
public class Address
{
@Column(name = "street_address1")
private String streetAddress1 = null;
@Column(name = "street_address2")
private String streetAddress2 = null;
@Column(name = "city")
private String city = null;
@Column(name = "state")
private String state = null;
@Column(name = "postal_code")
private String postalCode = null;
@Column(name = "country")
private String country = null;
@Id
@GeneratedValue(generator = "foreign")
@GenericGenerator(name = "foreign", strategy = "foreign", parameters = { @Parameter(value = "customer", name = "property") })
@Column(name = "customer_id")
// this is id of the customer - as an address is always associated with a
// customer (it cannot exist independent of a customer)
private Long customerID = null;
@OneToOne
@JoinColumn(name = "customer_id")
// reference to the customer object. hibernate requires two-way object
// references even though we are modeling a one-to-one relationship.
private Customer customer = null;
In plain-speak this translates into the following :
Address does not have its own “ID” attribute. It will use the “ID” of the
Customer and the Customer table and the Address table are joined via this
“ID” attribute (i.e. “customer_id”).
Test code :
private void testSingleObjectPersistence()
{
Customer customer = setupSingleCustomer();
// save an object
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
Long custID = (Long) session.save(customer);
tx.commit();
session.close();
System.out.println("Customer id : " + custID);
}
private Customer setupSingleCustomer()
{
Address address = new Address();
address.setCity("Austin");
address.setCountry("U.S.A");
address.setPostalCode("78701");
address.setState("Texas");
address.setStreetAddress1("301 Lavaca Street");
ContactInformation ci = new ContactInformation();
ci.setEmailAddress("info@gingermanpub.com");
ci.setWorkPhone("512-473-8801");
Customer customer = new Customer();
customer.setAccountNumber("90000200901");
customer.setFirstName("Gingerman");
customer.setLastName("Pub");
customer.setMiddleName("Beer");
customer.setSalutation("Sir");
customer.setAddress(address);
customer.setContactInfo(ci);
address.setCustomer(customer);
ci.setCustomer(customer);
return customer;
}
Once all the above changes have been made, Hibernate is actually able to persist the objects.
Here are the links to the files in case you want to take a detailed look at the code.
Hopefully you found this post helpful, and as always, please feel free to leave your feedback …
Leave a comment