Open In App

JPA – Cascading Operations

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

In Java, JPA is defined as Java Persistence API, which simplifies the process of managing relational data in Java applications. One of the key features of the JPA is Cascading Operations, which allow the propagation of state changes from one entity to the related entities of the JPA application.

It enables the automatic persistence, removal, and detachment of the related entities when changes are made to the parent entity. It ensures data consistency and simplifies the management of the object graphs in the application.

Cascade operations:

  • CascadeType.ALL: The ALL cascade type can propagate all operations, like the PERSIST, MERGE, REMOVE, REFRESH, and DETACH to the child entities of the JPA application.
  • CascadeType.PERSIST: The PERSIST cascade type can propagate the persist operations when the parent entity is persisted and the operation cascades to the child entities.
  • CascadeType.MERGE: The MERGE cascade type can propagate the merge operation and its parent entity is merged the operation cascades to its child entities of the JPA application.
  • CascadeType.REMOVE: The REMOVE cascade type can propagate the remove operation when the parent entity is removed then the operation cascades to its the child entities of JPA application.
  • CascadeType.REFRESH: The REFRESH cascade type can propagates the refresh operation when the parent entity is refreshed when the operation cascades to its the child entities of the JPA application.

Steps to Implement Cascade operations

1. Define the Entity classes with Relationships

We can define the entity class that can represent the domain model and these can be annotation to mark them as entities and define their relationship between the entities.

Parent Entity:

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

@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private List<Child> children = new ArrayList<>();

// Getter and Setter methods
}

Child Entity:

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

@ManyToOne
private Parent parent;

// Getter and Setter methods
}

2. Configure the cascading behavior

We can use the cascade attribute of the relationship and its annotation to specify the cascade behavior for the entities associated with the application.

Example: In Parent class, the @OneToMany annotation can specify the cascade type. ALL, and it can indicating that all the operations like persist, merge, remove, refresh and detach,. It should be cascaded to the associated with Child entities of the application.

3. Perform the operations and Observe cascading Effects

After configuring the cascading behavior, it can perform the operations on the parent entity and observe how those operations cascade to the associated child entities.

EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();

try {
transaction.begin();

// Create a parent entity with Children
Parent parent = new Parent();
Child child1 = new Child();
Child child2 = new Child();
parent.getChildren().add(child1);
parent.getChildren().add(child2);
child1.setParent(parent);
child2.setParent(parent);

Persist Parent (Cascades to Children)
entityManager.persist(parent);

transaction.commit();
} catch (Exception e) {
if (transaction.isActive())
transaction.rollback();
e.printStackTrace();
} finally {
entityManager.close();
}

In the above example,

  • Parent entity is created along with the two child entities and they can associated with each other.
  • When the Parent entity persists due to cascading behavior specified, the persistence operation cascades to the associated with Child entities of the application.
  • Observing the database state before and after the execution of these operation will help in understanding how the cascading operations work in the application.

Project Implementation of the Cascade Operations in JPA

Step 1: First, we will create a JPA project using Intellij Idea IDE. The project named as jpa-cascade-operations-demo.

Step 2: Now, we will add the following dependencies into the JPA project:.

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


Now the project structure will look like the below image:


Project Structure


Step 3: Now, open the persistance.xml file and write the below code for the MYSQL database configuration of the database.

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="persistence_unit_name">
        <class>model.ParentEntity</class>
        <class>model.ChildEntity</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: After all the above steps, now create a package named model and create an entity class inside that package named ParentEntity.

Go to src > main > java > model > ParentEntity and write the below code file.

Java
package model;

import jakarta.persistence.*;

import java.util.ArrayList;
import java.util.List;

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

    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
    private List<ChildEntity> children = new ArrayList<>();

    // Getter and Setter methods

    public Long getId() {
        return id;
    }

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

    public List<ChildEntity> getChildren() {
        return children;
    }

    public void setChildren(List<ChildEntity> children) {
        this.children = children;
    }


    @Override
    public String toString() {
        return "ParentEntity{" +
                "id=" + id +
                '}';
    }
}


Step 5: After all the above steps, now create a package named model and create an entity class inside that package named ChildEntity.

Go to src > main > java > model > ChildEntity and write the below code file.

Java
package model;

import jakarta.persistence.*;

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

    @ManyToOne
    private ParentEntity parent;

    // Getter and Setter methods

    public Long getId() {
        return id;
    }

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

    public ParentEntity getParent() {
        return parent;
    }

    public void setParent(ParentEntity parent) {
        this.parent = parent;
    }

    @Override
    public String toString() {
        return "ChildEntity{" +
                "id=" + id +
                '}';
    }
}


Step 6: Create a new Java class and name it MainApplication.

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

Java
import jakarta.persistence.*;
import model.ChildEntity;
import model.ParentEntity;

import java.util.List;


public class MainApplication {
    public static void main(String[] args) {
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence_unit_name");
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        try {
            transaction.begin();

            // Create Parent Entity with Children
            ParentEntity parent = new ParentEntity();
            ChildEntity child1 = new ChildEntity();
            ChildEntity child2 = new ChildEntity();
            parent.getChildren().add(child1);
            parent.getChildren().add(child2);
            child1.setParent(parent);
            child2.setParent(parent);

            // Persist Parent (Cascades to Children)
            entityManager.persist(parent);

            transaction.commit();

            // Print Parent and Child tables data
            printParentAndChildData(entityManager);

        } catch (Exception e) {
            if (transaction.isActive())
                transaction.rollback();
            e.printStackTrace();
        } finally {
            entityManager.close();
            entityManagerFactory.close();
        }
    }

    private static void printParentAndChildData(EntityManager entityManager) {
        System.out.println("Parent Table:");
        Query parentQuery = entityManager.createQuery("SELECT p FROM ParentEntity p");
        List<ParentEntity> parents = parentQuery.getResultList();
        for (ParentEntity parent : parents) {
            System.out.println(parent);
        }

        System.out.println("\nChild Table:");
        Query childQuery = entityManager.createQuery("SELECT c FROM ChildEntity c");
        List<ChildEntity> children = childQuery.getResultList();
        for (ChildEntity child : children) {
            System.out.println(child);
        }
    }
}


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-cascade-operations-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>jpa-cascade-operations-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>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</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>
    </dependencies>

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


Step 8: Once the project is done, run the application, and we will get the output like the below image.

Output in Console

If we follow the above steps, then we can successfully demonstrate the cascading operations of the JPA application.



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

Similar Reads