{noformat}When using HQL to DELETE a parent entity, the delete is not cascaded to child entity.
Here is a snippet of code that has the issues, detailed test case is below. transaction.begin(); // Use HQL to delete the parent. With CASCADE.ALL, // the child should be deleted. --- DOES NOT DELETE Query query = em.createQuery("DELETE FROM ParentEntity WHERE id = :parentId"); query.setParameter("parentId", parentId); query.executeUpdate(); transaction.commit();
But this piece of code cascades and deletes the child entity.
// Delete using EM ---- WORKS FINE! int parentId = parentEntity1.getId(); transaction.begin(); ParentEntity retrievedParent = em.find(ParentEntity.class, parentId); em.remove(retrievedParent); transaction.commit();
-- Database tables needed for the test case
create table TEST.TEST_PARENT_TABLE ( ID INTEGER not null primary key, NAME VARCHAR(256) ); create table TEST.TEST_CHILD_TABLE ( ID INTEGER not null primary key, NAME VARCHAR(256) );{noformat}
----ParentEntity.java --------
{noformat}package com.example;
import jakarta.persistence.*; import java.io.Serializable; import org.hibernate.annotations.NotFound; import org.hibernate.annotations.NotFoundAction;
@Entity @Table(name = "TEST_PARENT_TABLE", schema = "TEST") public class ParentEntity implements Serializable { private Integer id; private String name; private ChildEntity childEntity; @Id @Column(name = "ID") public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(name = "NAME") public String getName() { return name; } public void setName(String name) { this.name = name; } @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) @PrimaryKeyJoinColumn(name = "ID") @NotFound(action = NotFoundAction.IGNORE) public ChildEntity getChildEntity() { return childEntity; } public void setChildEntity(ChildEntity childEntity) { this.childEntity = childEntity; }{noformat}
--ChildEntity.java
{noformat}package com.example;
import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; import java.io.Serializable;
@Entity @Table(name = "TEST_CHILD_TABLE", schema = "TEST") public class ChildEntity implements Serializable { private Integer id; private String name; @Id @Column(name = "ID") public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(name = "NAME") public String getName() { return name; } public void setName(String name) { this.name = name; } } {noformat} --JUnit Test
{noformat} package com.example;
import static org.junit.Assert.assertNull;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.EntityTransaction; import jakarta.persistence.Query; import org.junit.After; import org.junit.Before; import org.junit.Test;
public class TestParentChildRelationship { private EntityManagerFactory emf; private EntityManager em;
@Before public void setup() { emf = JpaConfig.getEntityManagerFactory(); em = emf.createEntityManager(); }
@After public void tearDown() { if (em != null) { em.close(); } if (emf != null) { emf.close(); } }
@Test public void testParentChildRelationship() { EntityTransaction transaction = em.getTransaction(); transaction.begin(); // Create Parent entity 1 ParentEntity parentEntity1 = new ParentEntity(); parentEntity1.setId(1); parentEntity1.setName("parent entity 1"); ChildEntity childEntity1 = new ChildEntity(); childEntity1.setId(1); childEntity1.setName("Child of parent entity 1"); parentEntity1.setChildEntity(childEntity1); em.persist(parentEntity1);
// Create Parent entity 2 ParentEntity parentEntity2 = new ParentEntity(); parentEntity2.setId(2); parentEntity2.setName("parent entity 2"); ChildEntity childEntity2 = new ChildEntity(); childEntity2.setId(2); childEntity2.setName("Child of parent entity 2"); parentEntity2.setChildEntity(childEntity2); em.persist(parentEntity2); transaction.commit();
// Delete using EM int parentId = parentEntity1.getId(); transaction.begin(); ParentEntity retrievedParent = em.find(ParentEntity.class, parentId); em.remove(retrievedParent); transaction.commit();
// Delete using HQL parentId = parentEntity2.getId(); transaction = em.getTransaction(); transaction.begin(); // Use HQL to delete the parent .... with cascade all, the child should be deleted. Query query = em.createQuery("DELETE FROM ParentEntity WHERE id = :parentId"); query.setParameter("parentId", parentId); query.executeUpdate(); transaction.commit(); assertNull( "Parent entity 1 should be deleted", em.find(ParentEntity.class, parentEntity1.getId())); assertNull( "Parent entity 2 should be deleted", em.find(ParentEntity.class, parentEntity2.getId())); assertNull( "Child entity 1 should be deleted along with the parent", em.find(ChildEntity.class, childEntity1.getId())); assertNull( "Child entity 2 should be deleted along with the parent", em.find(ChildEntity.class, childEntity2.getId())); } }{noformat} |
|