Hibernate One-to-One Mapping Example

In this tutorial, we will demonstrate how to set up a one-to-one mapping between two entities using Hibernate annotations. We will create an example with Employee and EmployeeDetails entities to illustrate this mapping.

Prerequisites

  1. Java Development Kit (JDK) 21 or higher: Ensure JDK is installed and configured on your system.
  2. Integrated Development Environment (IDE): IntelliJ IDEA, Eclipse, or any other IDE.
  3. Maven: Ensure Maven is installed and configured on your system.

Step 1: Create a Maven Project

  1. Open your IDE and create a new Maven project.
  2. Update the pom.xml file to include Hibernate and other required dependencies.
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>hibernate-one-to-one-example</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.hibernate.orm</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>6.2.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.200</version>
        </dependency>
    </dependencies>
</project>

Explanation

  • Hibernate Core Dependency: Includes the main Hibernate framework.
  • SLF4J Dependencies: Used for logging.
  • H2 Database Dependency: An in-memory database for testing purposes.

Step 2: Create Hibernate Configuration File

Create a file named hibernate.cfg.xml in the src/main/resources directory.

<?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>
        <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
        <property name="hibernate.connection.driver_class">org.h2.Driver</property>
        <property name="hibernate.connection.url">jdbc:h2:mem:testdb</property>
        <property name="hibernate.connection.username">sa</property>
        <property name="hibernate.connection.password"></property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
    </session-factory>
</hibernate-configuration>

Explanation

  • Dialect: Specifies the SQL dialect (H2 in this case).
  • Connection Properties: Configure the JDBC connection to the H2 database.
  • hbm2ddl.auto: Automatically manages the database schema (update existing schema).
  • show_sql: Prints SQL statements to the console.
  • format_sql: Formats SQL statements.

Step 3: Create the Employee Entity Class

Create a package named com.example.entity and a class named Employee.

package com.example.entity;

import jakarta.persistence.*;

@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "details_id", referencedColumnName = "id")
    private EmployeeDetails employeeDetails;

    public Employee() {}

    public Employee(String name, EmployeeDetails employeeDetails) {
        this.name = name;
        this.employeeDetails = employeeDetails;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public EmployeeDetails getEmployeeDetails() {
        return employeeDetails;
    }

    public void setEmployeeDetails(EmployeeDetails employeeDetails) {
        this.employeeDetails = employeeDetails;
    }

    @Override
    public String toString() {
        return "Employee{id=" + id + ", name='" + name + '\'' + ", employeeDetails=" + employeeDetails + '}';
    }
}

Step 4: Create the EmployeeDetails Entity Class

Create a class named EmployeeDetails in the same package.

package com.example.entity;

import jakarta.persistence.*;

@Entity
public class EmployeeDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String address;
    private String phoneNumber;

    @OneToOne(mappedBy = "employeeDetails")
    private Employee employee;

    public EmployeeDetails() {}

    public EmployeeDetails(String address, String phoneNumber) {
        this.address = address;
        this.phoneNumber = phoneNumber;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getAddress() {
        return address;
    }

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

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

    @Override
    public String toString() {
        return "EmployeeDetails{id=" + id + ", address='" + address + '\'' + ", phoneNumber='" + phoneNumber + '\'' + '}';
    }
}

Explanation

  • @Entity: Marks the class as an entity.
  • @Id: Marks the field as the primary key.
  • @GeneratedValue: Specifies the strategy for generating values for the primary key.
  • @OneToOne: Defines a one-to-one relationship between Employee and EmployeeDetails.
  • @JoinColumn: Specifies the foreign key column.
  • @OneToOne(mappedBy = "employeeDetails"): Specifies the inverse side of the relationship.

Step 5: Create a Hibernate Utility Class

Create a package named com.example.util and a class named HibernateUtil.

package com.example.util;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {
    private static SessionFactory sessionFactory;

    static {
        try {
            Configuration configuration = new Configuration().configure();
            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                    .applySettings(configuration.getProperties()).build();
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

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

Explanation

  • Configuration: Loads Hibernate configuration from hibernate.cfg.xml.
  • ServiceRegistry: Builds the service registry from the configuration settings.
  • SessionFactory: Provides sessions to interact with the database.

Step 6: Create Main Class

Create a package named com.example and a class named Main.

package com.example;

import com.example.entity.Employee;
import com.example.entity.EmployeeDetails;
import com.example.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class Main {
    public static void main(String[] args) {
        // Initialize session and transaction
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = session.beginTransaction();

        // Create employee details
        EmployeeDetails employeeDetails = new EmployeeDetails("123 Main St", "123-456-7890");

        // Create employee
        Employee employee = new Employee("John Doe", employeeDetails);

        // Save employee (this will also save employee details due to cascade)
        session.save(employee);
        transaction.commit();
        session.close();

        // Retrieve and display employee
        session = HibernateUtil.getSessionFactory().openSession();
        Employee retrievedEmployee = session.get(Employee.class, employee.getId());
        System.out.println("Retrieved Employee: " + retrievedEmployee);
        session.close();

        // Close the SessionFactory
        HibernateUtil.getSessionFactory().close();
    }
}

Explanation

  • Session: Opens a session to interact with the database.
  • Transaction: Begins and commits a transaction for database operations.
  • Save: Persists the entity to the database.

Step 7: Run the Application

  1. Run the Main class.
  2. The output in the console should be:
Hibernate: create table Employee (id bigint generated by default as identity, details_id bigint, name varchar(255), primary key (id))
Hibernate: create table EmployeeDetails (id bigint generated by default as identity, address varchar(255), phoneNumber varchar(255), primary key (id))
Hibernate: alter table Employee add constraint FKqln1lkwqv9r7lq64dq43oi5sl foreign key (details_id) references EmployeeDetails
Hibernate: insert into EmployeeDetails (address, phoneNumber) values (?, ?)
Hibernate: insert into Employee (details_id, name) values (?, ?)
Hibernate: select employee0_.id as id1_0_0_, employee0_.details_id as details_3_0_0_, employee0_.name as name2_0_0_, employeedet1_.id as id1_1_1_, employeedet1_.address as address2_1_1_, employeedet1_.phoneNumber as phoneNum3_1_1_ from Employee employee0_ left outer join EmployeeDetails employeedet1_ on employee0_.details_id=employeedet1_.id where employee0_.id=?
Retrieved Employee: Employee{id=1, name='John Doe', employeeDetails=EmployeeDetails{id=1, address='123 Main St', phoneNumber='123-456-7890'}}

Conclusion

You have successfully created an example using Hibernate to demonstrate a one-to-one mapping with annotations. This tutorial covered setting up a Maven project, configuring Hibernate, creating entity classes with a one-to-one relationship, and performing basic CRUD operations.


Comments