This Hibernate tutorial is going to provide an example application that manages a bidirectional one-to-one association on a primary key which is described by the following entity relationship diagram:

 one-to-one with primary key entity relationship diagram

In this relationship, a product has one and only one detail information. Both the parent table (product) and child table (product_detail) share a same primary key (product_id). Thus it is called one-to-one association on a primary key. Let’s see how to model this relationship in Hibernate.

Software programs/libraries used this tutorial:

Table of content:

    1. Creating database and tables
    2. Setting up Eclipse project
    3. Writing Hibernate Model Classes
    4. Writing Hibernate Mapping Files
    5. Writing Hibernate Configuration File
    6. Coding a Test Program

 

1. Creating database and tables

Let’s create a MySQL database called productsdb with two tables product and product_detail. If you are using MySQL Workbench, execute the following script in a SQL Editor:

create database productsdb;
use productsdb;

CREATE TABLE `product` (
  `product_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(128) NOT NULL,
  `description` varchar(512) NOT NULL,
  `price` float NOT NULL,
  PRIMARY KEY (`product_id`)
);

CREATE TABLE `product_detail` (
  `product_id` int(11) NOT NULL,
  `part_number` varchar(45) NOT NULL,
  `dimension` varchar(45) NOT NULL,
  `weight` float NOT NULL,
  `manufacturer` varchar(45) NOT NULL,
  `origin` varchar(45) NOT NULL,
  PRIMARY KEY (`product_id`)
);

If you are using MySQL Command Line Client program, type the following command:

source Path\To\The\Script\File\MySQLscript.sql

You can find the MySQLscript.sql file the attached project or save it from the above script. The following screenshot shows structure of the newly created database:

productsdb database structure


2. Setting up Eclipse project

Using Eclipse IDE to create a standard Java project that has the following structure:

Hibernate one-to-one primary key project structure in Eclipse

The project consists of the following files:

    • Model classes: Product.java and ProductDetail.java
    • Hibernate XML mapping files: Product.hbm.xml and ProductDetail.hbm.xml
    • Hibernate XML configuration file: hibernate.cfg.xml
    • Test program: ProductsManager.java
    • Hibernate required JAR libraries and MySQL Connector Java driver:
      • hibernate-core-4.2.2.Final.jar
      • hibernate-commons-annotations-4.0.2.Final.jar
      • mysql-connector-java-5.1.25-bin.jar
      • jboss-transaction-api_1.1_spec-1.0.1.Final.jar
      • hibernate-jpa-2.0-api-1.0.1.Final.jar
      • jboss-logging-3.1.0.GA.jar
      • antlr-2.7.7.jar
      • dom4j-1.6.1.jar
      • javassist-3.15.0-GA.jar
    • MySQL script file: MySQLscript.sql

You can find the above Hibernate libraries under hibernate-release-VERSION\lib\required directory from Hibernate distribution archive.

 


3. Writing Hibernate Model Classes

To model the tables product and product_detail in Java, create the following two JavaBean-style classes:

File net\codejava\hibernate\Product.java:

package net.codejava.hibernate;

public class Product {
	private long productId;
	private String name;
	private String description;
	private float price;
	private ProductDetail productDetail;

	public Product() {
	}

	public ProductDetail getProductDetail() {
		return productDetail;
	}

	public void setProductDetail(ProductDetail detail) {
		this.productDetail = detail;
	}

	// other getters and setters
}

 

File net\codejava\hibernate\ProductDetail.java:

package net.codejava.hibernate;

public class ProductDetail {
	private long productId;
	private String partNumber;
	private String dimension;
	private float weight;
	private String manufacturer;
	private String origin;
	private Product product;

	public ProductDetail() {
	}

	public Product getProduct() {
		return product;
	}

	public void setProduct(Product product) {
		this.product = product;
	}

	// other getters and setters
}

NOTES: Both the Product and ProductDetail classes have mutual reference to each other, through the properties productDetail and product, respectively. This is required for a bidirectional one-to-one association in which we can navigate the child entity from the parent and vice-versa, for example:

ProductDetail child = product.getProductDetail();

Product parent = detail.getProduct();

 


4. Writing Hibernate Mapping Files

Create two XML files corresponding to the two above model classes with the following content:

File net\codejava\hibernate\Product.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="net.codejava.hibernate">
	<class name="Product" table="PRODUCT">
		<id name="productId" column="PRODUCT_ID">
			<generator class="native"/>
		</id>
		<property name="name" column="NAME" />
		<property name="description" column="DESCRIPTION" />
		<property name="price" column="PRICE" type="float" />
		
		<one-to-one name="productDetail" cascade="all" class="ProductDetail" />
	</class>	
</hibernate-mapping>        

 

File net\codejava\hibernate\ProductDetail.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="net.codejava.hibernate">
	<class name="ProductDetail" table="PRODUCT_DETAIL">
		<id name="productId" column="PRODUCT_ID">
			<generator class="foreign">
				<param name="property">product</param>
			</generator>
		</id>
		<property name="partNumber" column="PART_NUMBER" />
		<property name="dimension" column="DIMENSION" />
		<property name="weight" column="WEIGHT" type="float" />
		<property name="manufacturer" column="MANUFACTURER" />
		<property name="origin" column="ORIGIN" />
		
		<one-to-one name="product" constrained="true" class="Product" />
	</class>	
</hibernate-mapping>

 

NOTES: The <one-to-one> element is used on both sides to enforce their one-to-one relationship, and the <generator class=”foreign”> element in the ProductDetail.hbm.xml file enforces that the product_detail table’s primary key is generated based on the product table’s primary key.


5. Writing Hibernate Configuration File

Following is content of the Hibernate configuration file hibernate.cfg.xml:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>        
  <session-factory>
    <!-- Database connection settings -->
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost:3306/productsdb</property>
    <property name="connection.username">root</property>
    <property name="connection.password">secret</property>
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="show_sql">true</property>
    
    <mapping resource="net/codejava/hibernate/Product.hbm.xml"/>
    <mapping resource="net/codejava/hibernate/ProductDetail.hbm.xml"/>
      
  </session-factory>
</hibernate-configuration>

NOTES: Update the values of the properties connection.username and connection.password accordingly to your database username and password.

 


6. Coding a Test Program

Following is code of a demo program that obtains a Hibernate SessionFactory, persists a product (with detail) and lists all products:

package net.codejava.hibernate;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

/**
 * This program demonstrates using Hibernate framework to manage a
 * bidirectional one-to-one association on a primary key.
 * @author www.codejava.net
 *
 */
public class ProductsManager {

	public static void main(String[] args) {
		// loads configuration and mappings
		Configuration configuration = new Configuration().configure();
		ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
		registry.applySettings(configuration.getProperties());
		ServiceRegistry serviceRegistry = registry.buildServiceRegistry();
		
		// builds a session factory from the service registry
		SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		
		// obtains the session
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		
		// creates a new product
		Product product = new Product();
		product.setName("Civic");
		product.setDescription("Comfortable, fuel-saving car");
		product.setPrice(20000);
		
		// creates product detail
		ProductDetail detail = new ProductDetail();
		detail.setPartNumber("ABCDEFGHIJKL");
		detail.setDimension("2,5m x 1,4m x 1,2m");
		detail.setWeight(1000);
		detail.setManufacturer("Honda Automobile");
		detail.setOrigin("Japan");
		
		// sets the bi-directional association
		product.setProductDetail(detail);
		detail.setProduct(product);
		
		// persists the product
		session.save(product);
		
		// queries all products
		List<Product> listProducts = session.createQuery("from Product").list();
		for (Product aProd : listProducts) {
			String info = "Product: " + aProd.getName() + "\n";
			info += "\tDescription: " + aProd.getDescription() + "\n";
			info += "\tPrice: $" + aProd.getPrice() + "\n";
			
			ProductDetail aDetail = aProd.getProductDetail();
			info += "\tPart number: " + aDetail.getPartNumber() + "\n";
			info += "\tDimension: " + aDetail.getDimension() + "\n";
			info += "\tWeight: " + aDetail.getWeight() + "\n";
			info += "\tManufacturer: " + aDetail.getManufacturer() + "\n";
			info += "\tOrigin: " + aDetail.getOrigin() + "\n";
			
			System.out.println(info);
		}
		
		session.getTransaction().commit();
		session.close();		
	}

}

 

Output of the program:

Hibernate: insert into PRODUCT (NAME, DESCRIPTION, PRICE) values (?, ?, ?)

Hibernate: insert into PRODUCT_DETAIL (PART_NUMBER, DIMENSION, WEIGHT, ...

Hibernate: select product0_.PRODUCT_ID as PRODUCT1_0_, product0_.NAME as ...

Product: Civic

        Description: Comfortable, fuel-saving car

        Price: $20000.0

        Part number: ABCDEFGHIJKL

        Dimension: 2,5m x 1,4m x 1,2m

        Weight: 1000.0

        Manufacturer: Honda Automobile

        Origin: Japan

Result in the product table:

result records in product table

Result in the product_detail table:

result records in product detail table

Recommended Book: Java Persistence with Hibernate

Attachments:
Download this file (HibernateOne2OnePrimaryKeyXMLExample.zip)HibernateOne2OnePrimaryKeyXMLExample.zip[Eclipse project]6401 kB