In this Hibernate tutorial series, we are going to show you how to implement a bidirectional one-to-one association using JPA and Hibernate annotations. The annotations approach is preferred as an alternative to XML descriptor which is described in the tutorial Hibernate One-to-One With Primary Key XML Mapping Example. Let’s recall about the bidirectional one-to-one association by looking at the following entity relationship diagram:


one-to-one with primary key entity relationship diagram

As we can see, these two tables share a same primary key (product_id) so that it’s possible to navigate to a corresponding product_detail from a product and vice-versa, thus this is called bidirectional (two-ways) association on primary key.

In this tutorial, we will be developing a sample Hibernate program to manage the above product - product_detail association using the following pieces of software:

The software versions here are the latest as of this writing, but using similar versions is also possible. Here are the steps we should follow:

Table of content:

  1. Creating Database and Tables
  2. Creating Maven-Eclipse Project
  3. Coding Model Classes with Annotations
  4. Writing Hibernate Configuration File
  5. Writing a Test Program


1. Creating Database and Tables

Let’s create a database called productsdb containing two tables product and product_detail by executing the following MySQL script:

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`)

 We would have the following database structure:

productsdb database structure

2. Creating Maven-Eclipse Project

Eclipse Kepler has Maven integration by default, so creating a Maven project is quick and easy. Let’s create a Maven project with the following structure:

Hibernate one-to-one primary key annotations project structure

The project HibernateOne2OnePrimaryKeyAnnotationsExample consists of the following files:

  • Model classes: and
  • Hibernate XML configuration file: hibernate.cfg.xml
  • Test program:
  • Maven project: pom.xml

We specify two primary dependencies of hibernate-core and mysql-connector-java in the pom.xml file as follows:

<project xmlns="" 

The other related dependencies will be resolved automatically by Maven.


3. Coding Model Classes with Annotations

Create two model classes called and with the following source code:

File net\codejava\hibernate\

package net.codejava.hibernate;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

@Table(name = "PRODUCT")
public class Product {
	private long productId;
	private String name;
	private String description;
	private float price;
	private ProductDetail productDetail;

	public Product() {

	@Column(name = "PRODUCT_ID")
	public long getProductId() {
		return productId;

	@OneToOne(cascade = CascadeType.ALL)
	public ProductDetail getProductDetail() {
		return productDetail;

	// other getters and setters



 File net\codejava\hibernate\

package net.codejava.hibernate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

@Table(name = "PRODUCT_DETAIL")
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() {

	@GeneratedValue(generator = "foreigngen")
	@GenericGenerator(strategy = "foreign", name="foreigngen",
			parameters = @Parameter(name = "property", value="product"))
	@Column(name = "PRODUCT_ID")
	public long getProductId() {
		return productId;

	@Column(name = "PART_NUMBER")
	public String getPartNumber() {
		return partNumber;

	@OneToOne(mappedBy = "productDetail")
	public Product getProduct() {
		return product;

	// other getters and setters

Here, we use several annotations as you notice: The @Entity, @Table and @Column annotations are straightforward to understand. The others need some further explanations:

  • @Id and @GeneratedValue: are used in conjunction to map a field as the primary key of the table. Typically, the primary key’s values are auto-generated.
  • On the Product side, we use the @OneToOne and @PrimaryKeyJoinColumn annotations to tell Hibernate creates a one-to-one association with the ProductDetail and the join column is the primary key column.
  • On the ProductDetail side, we need to use the @GenericGenerator to specify a foreign key strategy in order to generate values for the product_id column as a foreign key. And the @OneToOne annotation tells Hibernate that the product field is a one-to-one association which is mapped by this productDetail.

4. Writing Hibernate Configuration File

We need to write XML descriptor in the hibernate.cfg.xml file to tell Hibernate which database to connect:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    <!-- 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 class="net.codejava.hibernate.Product"/>
    <mapping class="net.codejava.hibernate.ProductDetail"/>



5. Writing a Test Program

Write code for the test program ( as follows:

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 using 
 * annotations.
 * @author
public class ProductsManager {

	public static void main(String[] args) {
		// loads configuration and mappings
		Configuration configuration = new Configuration().configure();
		ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
		ServiceRegistry serviceRegistry = registry.buildServiceRegistry();
		// builds a session factory from the service registry
		SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		// obtains the session
		Session session = sessionFactory.openSession();
		// creates a new product
		Product product = new Product();
		product.setDescription("Comfortable, fuel-saving car");
		// creates product detail
		ProductDetail detail = new ProductDetail();
		detail.setDimension("2,5m x 1,4m x 1,2m");
		detail.setManufacturer("Honda Automobile");
		// sets the bi-directional association
		// persists the 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";


Output of the program:

Hibernate: insert into PRODUCT (description, name, price) values (?, ?, ?)
Hibernate: insert into PRODUCT_DETAIL (dimension,...) values (?, ?, ?, ?, ?, ?)
Hibernate: select product0_.PRODUCT_ID ... from PRODUCT product0_
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:

records in product table

Result in the product_detail table:

records in product detail table


Recommended Book: Java Persistence with Hibernate

Download this file ([Eclipse-Maven project]17 kB
Start learning on Udemy today!