Open In App

JPA – Collection Mapping

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

In Java, JPA can defined as Java Persistence API. Collection Mapping is a powerful feature that allows developers to map relationships between the entities and collections in the database. It allows the developers to map the collections of the objects from Java to corresponding database structures.

Collection Mapping

Collection Mapping in JPA refers to the mapping scheme between a Java Collection and other database tables such as Set, List, and Map. It enables developers to establish relationships between companies and collections, enabling efficient data storage and retrieval.

Steps to Implement Collection Mapping

Below are the steps to implement JPA Collection Mapping.

Step 1: Define the Entities

We can define the Entity classes in JPA that represent the objects that are persisted in the database and these classes are annotated with the @Entity.

Example:

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

@ManyToMany
@JoinTable(name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id"))
private List<Course> courses;
//getter and setters
}

In the above code snippet, we have defined the entity class named Student has a many-to-many relationship with the course class and it indicated by the @ManyToMany annotation on the Student attribute.

Step 2: Define the Collection Attributes

Within the entity classes, we define the collection attributes to represent the relationships. The Student class, the course attribute represents the collection of the courses taken by the students.

Step 3: Map Collections Using Annotations

We use the JPA annotations to the map these collection attributes to the database.

Example: The @ManyToMany annotation is used to map the many to many relationships and the mappedBy attributes specifies the inverse side of the relationships.

Step 4: Configure the Fetch Type

We configure the fetch type for the collections using the fetch attributes of the @OneToMany or @ManyToMany annotations. The fetch type specifies whether the associated the entities should be eagerly or the lazily loaded from the database.

Step 5: Persistence Operations

Finally, we can perform the CRUD operations using the JPA APIs to the interact with the database.

Collection Mapping related annotations

Annotations

Definition

@OneToMany

This annotation can be used to define the one-to-many relationship between the two entities.

Attributes:

  • mappedBy: it specifies the field in child entity that owns the relationship, and it indicates the inverse side of relationship.
  • cascade: Defines the cascade operation to the applied to associated entities. It allows the propagating the state transitions from parent entity to its associated child entities.
  • fetch: It configures the fetching strategy for the associated the entities. It specifies the associated entities should be the eagerly or lazily loaded from database.

@ManyToOne

This annotation is used to defines the many to one relationship between the two entities.

Attributes:

  • fetch: It configures the fetching strategy for associated entity.
  • optional: It indicates whether association is the optional or mandatory. If set to false, then the associated entity must always be present.
  • targetEntity: This specifies the target entity class if the attributes type is the superclass or the interface.

@ManyToMany

This annotation defines the many to many relationship between the two entities.

Attributes:

  • mappedBy: It specifies the field in child entity that owns the relationship, and it indicates the inverse side of relationship.
  • cascade: Defines the cascade operation to the applied to associated entities. it allows the propagating the state transitions from parent entity to its associated child entities.
  • targetEntity: This specifies the target entity class if the attributes type is the superclass or the interface.

@ElementCollection

This annotation can be used to define the collection of the basic or the embeddable tables.

Attributes:

  • targetClass: This specifies the class of the elements in the collection.
  • fetech: It configures the fetching strategy for the elements in collection.
  • cascade: Defines the cascade operations to applied to elements in the collections.

@JoinTable

This annotation specifies the mapping of the many to many relationships using the join table.

Attributes:

  • name: It specifies the name of join table.
  • joinColumns: Defines the foreign key columns of the join table that can reference the inverse entity.
  • inverseJoinColumns: Defines the foreign key columns of the join table that can reference the inverse entity.

@OrderBy

This annotation specifies the ordering of the elements in the collection.

Attributes:

  • value: It specifies the property by the which the elements should be ordered.
  • asc: It indicates whether the ordering should be ascending order or descending order.

Project Implementation of JPA Collection Mapping

Step 1: Create the new JPA project using the Intellj Idea named jpa-collection-mapping-demo.

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

Dependencies:

<!-- Database Driver (MySQL in this example) -->        
<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>

After successfully creating the project, the project structure will look like the below image.

File Structure


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="examplePU">
        <class>model.Student</class>
        <class>model.Employee</class>
        <class>model.Department</class>
        <class>model.Course</class>
        <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 new Java package named model. In that package, create the new Entity Java class named Student.

Go to src > main > java > model > Student and put the below code.

Java
package model;

import jakarta.persistence.*;

import java.util.List;

/**
 * Represents a student entity.
 */
@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    /** The list of courses associated with the student. */
    @ManyToMany
    @JoinTable(name = "student_course",
            joinColumns = @JoinColumn(name = "student_id"),
            inverseJoinColumns = @JoinColumn(name = "course_id"))
    private List<Course> courses;

    // Constructors, getters, and setters

    /**
     * Retrieves the student ID.
     */
    public Long getId() {
        return id;
    }

    /**
     * Sets the ID of the student.
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * Retrieves the name of the student.
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the name of the student.
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Retrieves the list of courses associated with the student.
     */
    public List<Course> getCourses() {
        return courses;
    }

    /**
     * Sets the list of courses associated with the student.
     */
    public void setCourses(List<Course> courses) {
        this.courses = courses;
    }
}


Step 5: Create the new Entity Java class named Course.

Go to src > main > java > model > Course and put the below code.

Java
package model;

import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Represents a course entity.
 */
@Entity
public class Course {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    /** The list of students enrolled in the course. */
    @ManyToMany(mappedBy = "courses")
    private List<Student> students = new ArrayList<>();

    // Constructors, getters, and setters

    /**
     * Retrieves the course ID.
     * Sets the ID of the course.
     */
    public Long getId() {
        return id;
    }

    /**
     * Retrieves the course name.
     * Sets the name of the course.
     */
    public String getName() {
        return name;
    }

    /**
     * Retrieves the list of students enrolled in the course.
     * Sets the list of students enrolled in the course.
     */
    public List<Student> getStudents() {
        return students;
    }

    /**
     * Sets the list of students enrolled in the course.
     */
    public void setStudents(List<Student> students) {
        this.students = students;
    }
}


Step 6: Create the new Entity Java class named Employee.

Go to src > main > java > model > Employee and put the below code.

Java
package model;

import jakarta.persistence.*;

/**
 * Represents an employee entity.
 */
@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /** The name of the employee. */
    private String name;

    /** department to which the employee belongs. */
    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;

    // Constructors, getters, and setters

    /**
     * Retrieves the employee iD.
     * Sets the ID of the employee.
     */
    public Long getId() {
        return id;
    }

    /**
     * Retrieves the employee name.
     * Sets the name of the employee.
     */
    public String getName() {
        return name;
    }

    /**
     * Retrieves the department to which the employee belongs.
     * Sets the department to which the employee belongs.
     */
    public Department getDepartment() {
        return department;
    }

    /**
     * Sets the department to which the employee belongs.
     */
    public void setDepartment(Department department) {
        this.department = department;
    }
}


Step 7: Create the new Entity Java class named Department.

Go to src > main > java > model > Department and put the below code.

Java
package model;

import jakarta.persistence.*;
import java.util.List;

/**
 * Represents a department entity.
 */
@Entity
public class Department {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    /** The list of employees belonging to this department. */
    @OneToMany(mappedBy = "department")
    private List<Employee> employees;

    // Constructors, getters, and setters

    /**
     * Retrieves the department ID.
     * Sets the ID of the department.
     */
    public Long getId() {
        return id;
    }

    /**
     * Retrieves the department name.
     * Sets the name of the department.
     */
    public String getName() {
        return name;
    }

    /**
     * Retrieves the list of employees belonging to this department.
     * Sets the list of employees belonging to this department.
     */
    public List<Employee> getEmployees() {
        return employees;
    }

    /**
     * Sets the list of employees belonging to this department.
     */
    public void setEmployees(List<Employee> employees) {
        this.employees = employees;
    }
}


Step 8: Create the new Java package named as util. In that package, create a new Java class named JPAUtil.

Go to src > main > java > util > JPAUtil and put the below code.

Java
package util;

import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;

/**
 * Utility class for managing JPA operations.
 */
public class JPAUtil {
    /** The name of the persistence unit. */
    private static final String PERSISTENCE_UNIT_NAME = "examplePU";

    /** The entity manager factory. */
    private static EntityManagerFactory entityManagerFactory;

    static {
        try {
            entityManagerFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
        } catch (Throwable ex) {
            System.err.println("Initial EntityManagerFactory creation failed: " + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    /**
     * Retrieves the entity manager factory.
     * @return The entity manager factory.
     */
    public static EntityManagerFactory getEntityManagerFactory() {
        return entityManagerFactory;
    }

    /**
     * Shuts down the entity manager factory.
     */
    public static void shutdown() {
        if (entityManagerFactory != null) {
            entityManagerFactory.close();
        }
    }
}


Step 9: Create the new Java class named MainApplication.

Go to src > main > java > MainApplication and put the below code.

Java
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import model.Course;
import model.Department;
import model.Employee;
import model.Student;
import util.JPAUtil;

import java.util.List;

/**
 * Main class for demonstrating JPA operations.
 */
public class MainApplication {
    /**
     * Main method to execute JPA operations.
     * @param args Command-line arguments.
     */
    public static void main(String[] args) {
        EntityManager entityManager = JPAUtil.getEntityManagerFactory().createEntityManager();

        // Add data to Department and Employee tables
        entityManager.getTransaction().begin();
        Department department1 = new Department();
        department1.setName("Engineering");
        entityManager.persist(department1);

        Department department2 = new Department();
        department2.setName("Marketing");
        entityManager.persist(department2);

        Employee employee1 = new Employee();
        employee1.setName("Syam");
        employee1.setDepartment(department1);
        entityManager.persist(employee1);

        Employee employee2 = new Employee();
        employee2.setName("Mikel Smith");
        employee2.setDepartment(department1);
        entityManager.persist(employee2);

        Employee employee3 = new Employee();
        employee3.setName("Eswar");
        employee3.setDepartment(department2);
        entityManager.persist(employee3);

        entityManager.getTransaction().commit();

        // Add data to Student and Course tables
        entityManager.getTransaction().begin();
        Student student1 = new Student();
        student1.setName("Mahesh");
        entityManager.persist(student1);

        Student student2 = new Student();
        student2.setName("Sirish");
        entityManager.persist(student2);

        Course course1 = new Course();
        course1.setName("Java Programming");
        course1.getStudents().add(student1);
        course1.getStudents().add(student2);
        entityManager.persist(course1);

        Course course2 = new Course();
        course2.setName("Database Management");
        course2.getStudents().add(student1);
        entityManager.persist(course2);

        entityManager.getTransaction().commit();

        // Print all data from Department and Employee tables
        printAllDepartments(entityManager);
        printAllEmployees(entityManager);

        // Print all data from Student and Course tables
        printAllStudents(entityManager);
        printAllCourses(entityManager);

        entityManager.close();
        JPAUtil.shutdown();
    }

    /**
     * Prints all departments.
     * @param entityManager The entity manager.
     */
    private static void printAllDepartments(EntityManager entityManager) {
        Query query = entityManager.createQuery("SELECT d FROM Department d");
        List<Department> departments = query.getResultList();
        System.out.println("Departments:");
        for (Department department : departments) {
            System.out.println(department.getId() + "\t" + department.getName());
        }
        System.out.println();
    }

    /**
     * Prints all employees.
     * @param entityManager The entity manager.
     */
    private static void printAllEmployees(EntityManager entityManager) {
        Query query = entityManager.createQuery("SELECT e FROM Employee e");
        List<Employee> employees = query.getResultList();
        System.out.println("Employees:");
        for (Employee employee : employees) {
            System.out.println(employee.getId() + "\t" + employee.getName() + "\t" + employee.getDepartment().getName());
        }
        System.out.println();
    }

    /**
     * Prints all students.
     * @param entityManager The entity manager.
     */
    private static void printAllStudents(EntityManager entityManager) {
        Query query = entityManager.createQuery("SELECT s FROM Student s");
        List<Student> students = query.getResultList();
        System.out.println("Students:");
        for (Student student : students) {
            System.out.println(student.getId() + "\t" + student.getName());
        }
        System.out.println();
    }

    /**
     * Prints all courses.
     * @param entityManager The entity manager.
     */
    private static void printAllCourses(EntityManager entityManager) {
        Query query = entityManager.createQuery("SELECT c FROM Course c");
        List<Course> courses = query.getResultList();
        System.out.println("Courses:");
        for (Course course : courses) {
            System.out.println(course.getId() + "\t" + course.getName());
            System.out.println("Students enrolled:");
            for (Student student : course.getStudents()) {
                System.out.println("\t- " + student.getName());
            }
        }
        System.out.println();
    }
}

pom.xml

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-collection-mapping-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>jpa-collection-mapping-demo</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 10: Once the project is completed, run the application. It will show the departments and employees along with their departments, with the students and the students enrolled as well as courses and courses. Refer the below image for the better understanding of the concept.

Output Screen

If we follow the above procedure, then we can successfully build the JPA application of the demonstration of the creating the Collection Mapping of the entity of the JPA Application.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads