Open In App

JPA One-to-One Mapping

Last Updated : 23 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In Java, JPA can define the Java Persistence API, One-to-one mapping is the common association relationship where one instance of the entity is associated with exactly one instance of another entity.

Understanding of the JPA – One-to-One Mapping

One-to-one mapping can establish the relationship between the two entities where each instance of the one entity is associated with exactly one instance of the other entity. Let’s illustrate the example of the Person entity having a one-to-one relationship with an Address entity.

Steps to Implementation

1. Define the Entities:

We can create the two entity classes Person and Address and it can establish the one-to-one relationship between them using the annotations of the JPA application.

Person Entity:

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

@OneToOne(mappedBy = "person", cascade = CascadeType.ALL)
private Address address;

// Constructors, getters, and setters
}

Address Entity:

@Entity
public class Address {
@Id
private Long id;

@OneToOne
@MapsId
private Person person;

private String city;

// Constructors, getters, and setters
}

2. Implement the Mapping:

We can use the annotations to define the mapping between the entities and it can annotate the corresponding fields in the both entities with @OneToOne.

@OneToOne(mappedBy = "person", cascade = CascadeType.ALL)
private Address address;

3. Handles the Foreign Key:

We can ensures that the foreign key referencing the primary key of the one entity is present in the other entity of the application.

4. Test the Mapping:

We can persist the instances of the entities and retrieves them to the verify the mapping of the JPA application.

// Code to persist entities and retrieve them to verify the mapping
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PU_NAME");
EntityManager em = emf.createEntityManager();

em.getTransaction().begin();

Person person = new Person();
person.setName("John Doe");
em.persist(person);

Address address = new Address();
address.setPerson(person);
address.setCity("New York");
em.persist(address);

em.getTransaction().commit();

// Retrieve person and address
Person retrievedPerson = em.find(Person.class, person.getId());
Address retrievedAddress = retrievedPerson.getAddress();

System.out.println("Person: " + retrievedPerson.getName());
System.out.println("Address: " + retrievedAddress.getCity());

em.close();
emf.close();

Subtopics:

Shared Primary Key:

In the shared primary key mapping, the primary key of the owning entity is also the primary key of associated entity and it can simplifies the mapping and ensures the one-to-one relationship.

Foreign Key association:

In this approach, The associated entity can holds the foreign key referencing the primary key of the owning entity. This is the common method for the implementing one-to-one mapping and it can especially when the associated entity can exist independently.

Project to Implement One-To-One Mapping in JPA

Step 1: Create the new JPA project using the IntelliJ Idea named jpa-one-to-one-mapping. After creating the project, the file structure looks like the below image.

oneonefile

file structure


Step 2: Open the pom.xml and add the below dependencies into the project.

        <dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.0.2.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>


Step 3: Open the persistence.xml and put the below code into the project and it can configure the database of the project.

XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
             version="3.0">
    <persistence-unit name="jpa-example">

        <properties>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/example"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>

    </persistence-unit>
</persistence>


Step 4: Create the Java package named as the model in that package create the Java class named as the Person. Go to src > main > java > model > Person and put the below code.

Java
package model;

import jakarta.persistence.*;

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

    @OneToOne(mappedBy = "person", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Address address;

    // Constructors, getters, and setters
    public Person() {}

    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 Address getAddress() {
        return address;
    }

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


Step 5: Create the Java package named as the model in that package create the Java class named as the Address. Go to src > main > java > model > Address and put the below code.

Java
package model;

import jakarta.persistence.*;

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

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "person_id")
    private Person person;

    private String city;

    // Constructors, getters, and setters
    public Address() {}

    public Long getId() {
        return id;
    }

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

    public Person getPerson() {
        return person;
    }

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

    public String getCity() {
        return city;
    }

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


Step 6: Create the Java class named as the MainApplication. Go to src > main > java > MainApplication and put the below code.

Java
import jakarta.persistence.*;
import model.Address;
import model.Person;

public class MainApplication {
    public static void main(String[] args) {
        // Create EntityManagerFactory
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa-example");
        EntityManager em = emf.createEntityManager();

        // Begin transaction
        em.getTransaction().begin();

        // Create a person
        Person person = new Person();
        person.setName("Mahesh");
        em.persist(person);

        // Create an address
        Address address = new Address();
        address.setPerson(person);
        address.setCity("Hyderabad");
        em.persist(address);

        // Commit transaction
        em.getTransaction().commit();

        // Retrieve person and address
        Person retrievedPerson = em.find(Person.class, person.getId());

        // Check if person and associated address exist
        if (retrievedPerson != null && retrievedPerson.getAddress() != null) {
            Address retrievedAddress = retrievedPerson.getAddress();
            System.out.println("Person: " + retrievedPerson.getName());
            System.out.println("Address: " + retrievedAddress.getCity());
        } else {
            System.out.println("Person or associated Address not found.");
        }

        // Close EntityManager
        em.close();
        emf.close();
    }
}

pom.xml:

Below is the XML file after adding all dependencies at the time of project creation.

XML
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>jpa-one-to-one-mapping</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>jpa-one-to-one-mapping</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.target>11</maven.compiler.target>
        <maven.compiler.source>11</maven.compiler.source>
        <junit.version>5.9.2</junit.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.hibernate.orm</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>6.0.2.Final</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>3.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
        </plugins>
    </build>
</project>


Step 7: Once the project is completed, run the application, it will show person name and address as output. Refer the below output image for the better understanding of the concept.

oneonerun-compressed

Conclusion

One-To-One mapping in the JPA can enables the developers to represent the relationship between the entities where the each instance of the one entity is associated with the exactly one instance of the another entity. By the understanding of the concept, implementing the mapping and developers can effectively can manage the one-to-one relationship into the JPA applications.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads