Hibernate One-To-One Mapping(XML mapping)

In this tutorial we will write a simple Java project to demonstrate Hibernate one to one Mapping. We shall use HSQL as the database and Maven for creating the project and making it compatible with eclipse. We will first create a Java project using Maven and then will add Hibernate on it. HSQL database is used to make the project simple, as we can use in-memory database and we would need only a JAR file to be included in our project. If you have any questions, please post it in the comments section. If you are interested in receiving the future articles on Java topics, please subscribe here. If you are beginner for hibernate, please read the articles about introduction to hibernate, interceptors in hibernate and spring & hibernate integration. We also recommend good reference books for learning hibernate in our post about hibernate books.

hibernate-mapping

One To One Relationship

A one-to-one relationships occurs when one entity is related to exactly one occurrence in another entity. Consider the following relationship:

hibernate_onetoone_mapping

According to the relationship each Person should have a unique address. Hence we will need two tables namely PERSON and ADDRESS to create this relation. The relational model is shown below:
onetoone_table_relation

Hence following points would be included in our example project demonstrating One-to-One relationship :

  1. We will write two POJO classes (Person.java and Address.java ) and corresponding mapping files would be Person.hbm.xml and Address.hbm.xml respectively. Here the relation is, one address is assigned for one person only.
  2. To achieve one to one relationship, both tables have the same PERSON_ID as primary key. In ADDRESS table, PERSON_ID is the primary key and also a foreign key to PERSON table. This is the common way of define “one-to-one” table relationship.

Pre-Requisites

Following are the tools and technologies required for this project:

  1. Java JDK 5 or above
  2. Eclipse IDE 3.2 or above
  3. Maven 3.0 or above
  4. Hibernate 3.0 or above (Download from http://hibernate.org/downloads)
  5. HsqlDB (Download from http://hsqldb.org/)

1. Generating Maven Java project compatible with Eclipse

We will create a Java project using Maven (Refer post Creating Simple Java Project Using Apache Maven). Open the command line window and execute the following command:

mvn archetype:generate
-DgroupId=net.javabeat.hibernate
-DartifactId=HibernateOneToOneXML
-DarchetypeArtifactId=maven-archetype-quickstart
-DinteractiveMode=false

On execution of the above command, a java project HibernateOneToOneXML is created (In our case we have created it in the directory C:\HibernateProject). This java project already has a directory structure (as explained in the post (Refer post Creating Simple Java Project Using Apache Maven). To make this project compatible with eclipse, let’s execute the following command:

mvn eclipse:eclipse

2. Import project into Eclipse

Open Eclipse and import the above Java project as explained below:

File > Import… > General > Existing Projects into Workspace > Choose above Java project

Build-path settings
Goto Window > Preferences… > Java > Build Path > Classpath Variables >

  • Define new variable M2_REPO pointing to your local maven repository. (In our case it is:C:/Documents and Settings/Manisha/.m2/repository).
  • Define new variable HSQLDB pointing to the hsqldb.jar. (C:/tools/hsqldb-2.2.9/hsqldb/lib/hsqldb.jar).

classpath_setting

3. Adding the Hibernate and HSQLDB Dependency to pom.xml

We need to add the Hibernate, HSQLDB and some other dependencies to the Maven pom.xml as shown below:

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>net.javabeat.hibernate</groupId>
 <artifactId>HibernateOneToOneXML</artifactId>
 <packaging>jar</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>HibernateOneToOneXML</name>
 <url>http://maven.apache.org</url>
 <dependencies>
   <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>3.8.1</version>
     <scope>test</scope>
   </dependency>
<!-- Hibernate library dependecy start -->
  <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate</artifactId>
     <version>4.1.9.Final</version>
  </dependency>
  <dependency>
     <groupId>org.hsqldb</groupId>
     <artifactId>hsqldb</artifactId>
     <version>2.2.9</version>
  </dependency>
  <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-annotations</artifactId>
     <version>3.3.1.GA</version>
  </dependency>
  <dependency>
     <groupId>dom4j</groupId>
     <artifactId>dom4j</artifactId>
     <version>1.6.1</version>
  </dependency>
  <dependency>
     <groupId>commons-logging</groupId>
     <artifactId>commons-logging</artifactId>
     <version>1.1.1</version>
  </dependency>
  <dependency>
     <groupId>commons-collections</groupId>
     <artifactId>commons-collections</artifactId>
     <version>3.2.1</version>
  </dependency>
  <dependency>
     <groupId>cglib</groupId>
     <artifactId>cglib</artifactId>
     <version>2.2</version>
  </dependency>
  <dependency>
     <groupId>asm</groupId>
     <artifactId>asm</artifactId>
     <version>4.0</version>
  </dependency>
  <dependency>
     <groupId>dom4j</groupId>
     <artifactId>dom4j</artifactId>
     <version>1.6.1</version>
  </dependency>
  <dependency>
      <groupId>ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>1.2.3</version>
  </dependency>
  <dependency>
      <groupId>hibernate-tools</groupId>
      <artifactId>hibernate-tools</artifactId>
      <version>3.2.3.GA</version>
  </dependency>
  <dependency>
      <groupId>jta</groupId>
      <artifactId>jta</artifactId>
      <version>1.1</version>
  </dependency>
  <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.11</version>
  </dependency>
  <dependency>
      <groupId>oscache</groupId>
      <artifactId>oscache</artifactId>
      <version>2.1</version>
  </dependency>
  <dependency>
      <groupId>persistence-api</groupId>
      <artifactId>persistence-api</artifactId>
      <version>1.0</version>
   </dependency>
  <!-- Hibernate library dependecy end -->
</dependencies>
</project>
 

As a next step, let’s execute the following command so that maven will download all the required JARs and add the same to eclipse classpath.

mvn eclipse:eclipse

4. Create Model Classes

As a next step let’s create the model classes
src\main\java\net\javabeat\hibernate\Person.java and src\main\java\net\javabeat\hibernate\Address.java as below:

Person.java

package net.javabeat.hibernate;

import java.io.Serializable;

/**
 * Model class for Person
 */
public class Person implements Serializable {
	private Long personId;
	private String name;

	private Address address;

	public Person() {
	}

	public Long getPersonId() {
		return personId;
	}

	public void setPersonId(Long personId) {
		this.personId = personId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

}

Address.java

package net.javabeat.hibernate;

import java.io.Serializable;

public class Address implements Serializable {
	private String street;
	private String city;
	private String state;
	private String zipcode;
	private Person person;
	private Long personId;

	public Address() {

	}

	public Address(String street, String city, String state, String zipcode) {
		this.street = street;
		this.city = city;
		this.state = state;
		this.zipcode = zipcode;

	}

	public String getStreet() {
		return street;
	}

	public void setStreet(String street) {
		this.street = street;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	public String getZipcode() {
		return zipcode;
	}

	public void setZipcode(String zipcode) {
		this.zipcode = zipcode;
	}

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

	public Long getPersonId() {
		return personId;
	}

	public void setPersonId(Long personId) {
		this.personId = personId;
	}

}

Hibernate Mapping Files

Next let’s write a Hibernate XML Mapping files to the directory:/src/main/resources . Create the resources directory as follows: Right click on Project > New > Source Folder > Give folder name “/src/main/resources/” and click Finish.
Write the file src\main\resources\net\javabeat\hibernate\Person.hbm.xml for the model Person and
src\main\resources\net\javabeat\hibernate\Address.hbm.xml for the model class Address.
The contents of these files are as below:

Person.hbm.xml

 <?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 <hibernate-mapping>
 	<class name="net.javabeat.hibernate.Person" table="person">
 		<id name="personId" type="java.lang.Long">
 			<column name="PERSON_ID" />
 			<generator class="native" />
 		</id>

 		<property name="name" type="string">
 			<column name="NAME" length="10" not-null="true" unique="true" />
 		</property>
 		<one-to-one name="address" class="net.javabeat.hibernate.Address"
 			cascade="save-update"></one-to-one>
 	</class>
</hibernate-mapping>

Address.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
	<class name="net.javabeat.hibernate.Address" table="address">
		<meta attribute="class-description">This class contains the address of each person
			details.</meta>
		<id name="personId" type="java.lang.Long">
			<column name="PERSON_ID" />
			<generator class="foreign">
                <param name="property">person</param>
            </generator>

		</id>
		<one-to-one name="person" class="net.javabeat.hibernate.Person"
			constrained="true"></one-to-one>
		<property name="street" column="ADDRESS_STREET" type="string"
			length="250" />
		<property name="city" column="ADDRESS_CITY" type="string"
			length="50" />
		<property name="state" column="ADDRESS_STATE" type="string"
			length="50" />
		<property name="zipcode" column="ADDRESS_ZIPCODE" type="string"
			length="10" />

	</class>
</hibernate-mapping>

In the above hibernate mapping file we are implementing One-to-One relationship. For both the model classes we are using a single primary key personId. In Adress hbm file we have defined a foreign identifier generator so that primary it uses primary key of Person table.

5. Adding Hibernate Configuration file

As a next step let’s add the hibernate.cfg.xml to the directory:/src/main/resources . Write the new file hibernate.cfg.xml in this directory. The hibernate.cfg.xml is as follows:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings, Connect to HSQL, IN Memory  -->
        <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
		<property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
        <property name="connection.url">jdbc:hsqldb:mem:test</property>
		 <property name="connection.username">sa</property>
        <property name="connection.password"></property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>
        <property name="show_sql">true</property><property name="format_sql">true</property>

        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
        <!--create the database schema on startup if required -->
        <property name="hbm2ddl.auto">update</property>
       <!-- <mapping class="entities.Subscriber"/> -->
       <mapping resource="net/javabeat/hibernate/Person.hbm.xml"></mapping>
       <mapping resource="net/javabeat/hibernate/Address.hbm.xml"></mapping>

  </session-factory>
</hibernate-configuration>

In the above file we have set the database connection to HSQL-In memory database (mem is in-memeory, and test is the database name). The show_sql option, if set to true will display all the executed SQL queries on the console. The property hbm2ddl.auto , if set to update, will change the existing database schema on each start up. In the end we add the Person.hbm.xml and Address.hbm.xml files to the configuration.

Note : In case you want to use any other database then, you need to change these properties -
“dialect”, “connection.driver_class”, “connection.url”, “connection.username”, and “connection.password”

6. Create Utility class

Next, we will write a utility class to take care of Hibernate start up and retrieve the session easily. We will write the file src\main\java\net\javabeat\hibernate\HibernateUtil.java as below:

package net.javabeat.hibernate;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    private static final SessionFactory sessionFactory;
    static {
        try {
            sessionFactory = new Configuration().configure()
            .buildSessionFactory();
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

7. Revise the App class

Next we will revise the App.java (generated by Maven). This class tests the one-to-one relationship by creating and listing the person names and coressponding addresses as below:

package net.javabeat.hibernate;

import java.util.Iterator;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 * Main class
 *
 */
public class App {
	public static void main(String[] args) {
		System.out.println("Maven + Hibernate + HSQL XML One to One Mapping ");
		Session session = HibernateUtil.getSessionFactory().openSession();
		session.beginTransaction();
		App app = new App();

		Address address1 = new Address("M.G.Road", "Bangalore", "Karnataka",
				"56000");
		Address address2 = new Address("Tilak Road", "Pune", "Maharashtra",
				"411207");

		app.savePersonInfo("Jiya", address1);
		app.savePersonInfo("Manisha", address2);

		app.listPersonInfo();

	}

	public Long savePersonInfo(String personName, Address address) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		session.beginTransaction();
		Long personId = null;
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			Person person = new Person();
			person.setName(personName);

			person.setAddress(address);
			address.setPerson(person);
			session.save(person);

			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		return personId;
	}

	/*
	 * Lists the person's from database table
	 */
	public void listPersonInfo() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			@SuppressWarnings("unchecked")
			List<Person> personList = session.createQuery("from Person").list();
			for (Iterator<Person> iterator = personList.iterator(); iterator
					.hasNext();) {
				Person person = (Person) iterator.next();
				System.out.println(person.getName());
				System.out.println(person.getAddress().getStreet() + " "
						+ person.getAddress().getCity() + " "
						+ person.getAddress().getState() + " "
						+ person.getAddress().getZipcode());
			}
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

}

Here the savePersonInfo() method is used to save a new Person object and Address object to the database. In the savePersonInfo() method a new object of the Person class is created and the name value and address is set. The personId value is auto generated so the value need not be set here. We then save the Person object to the Address object. The session.save() method is used to persist the value in the database and once the value is saved, the id value (Primary key) is returned. Once the object is saved, the transaction is committed. If any exception occurs then the transaction is rolledback. The transaction ends either through commit or rollback action. Once the transaction ends the session is closed.

The listPersonInfo() method is used to list name of each person in PERSON table and their corresponding addresses from ADDRESS table. Here we use Hibernate Query Language (HQL). The query “from Person” returns a list of all the data in the PERSON table and their corresponding addresses from ADDRESS table. Note that in the HQL we only specify the java class names and not the table names. Later, using the for loop we iterate the list the data from Person and corresponding Address table and hence display them on the console.

8. Final project structure

Once you have created all these source files, your project structure should look like following:
onetoone_dir_struct

9. Execution of the above code

Now let us execute the code we created above. Let’s run the App class.
Right click on App.java >Run As > Java Application.
On start of each thread, a database schema will be created and the following actions will happen.

Output on the console:
Following output is displayed on the console:

Maven + Hibernate + HSQL XML One to One Mapping
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
Hibernate:
    insert
    into
        person
        (PERSON_ID, NAME)
    values
        (null, ?)
Hibernate:
    insert
    into
        address
        (ADDRESS_STREET, ADDRESS_CITY, ADDRESS_STATE, ADDRESS_ZIPCODE, PERSON_ID)
    values
        (?, ?, ?, ?, ?)
Hibernate:
    insert
    into
        person
        (PERSON_ID, NAME)
    values
        (null, ?)
Hibernate:
    insert
    into
        address
        (ADDRESS_STREET, ADDRESS_CITY, ADDRESS_STATE, ADDRESS_ZIPCODE, PERSON_ID)
    values
        (?, ?, ?, ?, ?)
Hibernate:
    select
        person0_.PERSON_ID as PERSON1_0_,
        person0_.NAME as NAME0_
    from
        person person0_
Hibernate:
    select
        address0_.PERSON_ID as PERSON1_1_0_,
        address0_.ADDRESS_STREET as ADDRESS2_1_0_,
        address0_.ADDRESS_CITY as ADDRESS3_1_0_,
        address0_.ADDRESS_STATE as ADDRESS4_1_0_,
        address0_.ADDRESS_ZIPCODE as ADDRESS5_1_0_
    from
        address address0_
    where
        address0_.PERSON_ID=?
Hibernate:
    select
        address0_.PERSON_ID as PERSON1_1_0_,
        address0_.ADDRESS_STREET as ADDRESS2_1_0_,
        address0_.ADDRESS_CITY as ADDRESS3_1_0_,
        address0_.ADDRESS_STATE as ADDRESS4_1_0_,
        address0_.ADDRESS_ZIPCODE as ADDRESS5_1_0_
    from
        address address0_
    where
        address0_.PERSON_ID=?
Jiya
M.G.Road Bangalore Karnataka 56000
Manisha
Tilak Road Pune Maharashtra 411207

Summary

In this post we first created a simple Java project using Maven and made it compatible with eclipse. Then we added the Hibernate one to one relation by creating two hibernate XML files Person and Address and relating them uing the one-to-one tag in both the files. We used a simple HSQL database, to insert records into Person and Address table and also listed these records. In the next article we shall look into Hibernate One-To-One Mapping using Java Annotations. If you have any questions, please post it in the comments section. If you are interested in receiving the future articles on Java topics, please subscribe here

Comments

comments

About Manisha Patil

Manisha S Patil, currently residing at Pune India. She is currently working as freelance writer for websites. She had earlier worked at Caritor Bangalore, TCS Bangalore and Sungard Pune. She has 5 years of experience in Java/J2EE technologies.

Speak Your Mind

*

Close
Please support the site
By clicking any of these buttons you help our site to get better