From 5c81a828f129977a1bfb3c7f996b15e209d1d318 Mon Sep 17 00:00:00 2001 From: Thibault Cordel Date: Fri, 13 Dec 2024 15:46:37 +0100 Subject: [PATCH] tests: Transaction commit fails Commiting a transaction in which a deletion has been made on an entitu referenced by others element in cache results in an exception. may be related to #055570c8af7c8455d6ae318d589c47441c55850c This issue was initialy raised in spring-data-jpa but then redirected to hibernate (https://github.com/spring-projects/spring-data-jpa/issues/3712) --- .../test/jpa/cascade/DeleteCascadeTest.java | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/jpa/cascade/DeleteCascadeTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/cascade/DeleteCascadeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/cascade/DeleteCascadeTest.java new file mode 100644 index 000000000000..3466d959fd13 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/cascade/DeleteCascadeTest.java @@ -0,0 +1,130 @@ +package org.hibernate.orm.test.jpa.cascade; + +import jakarta.persistence.*; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; +import org.hibernate.query.criteria.HibernateCriteriaBuilder; +import org.hibernate.query.criteria.JpaCriteriaQuery; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import java.util.List; + +@DomainModel( + annotatedClasses = { + DeleteCascadeTest.A.class, + DeleteCascadeTest.B.class, + DeleteCascadeTest.C.class, + } +) +@SessionFactory +class DeleteCascadeTest { + + @Entity + public static class A { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + } + + @Entity + public static class B { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + @ManyToOne + @JoinColumn(name = "a_id", nullable = false) + @OnDelete(action = OnDeleteAction.CASCADE) + private A a; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public A getA() { + return a; + } + + public void setA(A a) { + this.a = a; + } + + } + + @Entity + public static class C { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + @ManyToOne + @JoinColumn(name = "b_id", nullable = false) + @OnDelete(action = OnDeleteAction.CASCADE) + private B b; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public B getB() { + return b; + } + + public void setB(B b) { + this.b = b; + } + + } + + + @Test + void testRemove(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + A a = new A(); + session.persist(a); + + B bb = new B(); + bb.setA(a); + session.persist(bb); + + C c = new C(); + c.setB(bb); + session.persist(c); + }); + scope.inTransaction( + session -> { + + HibernateCriteriaBuilder cb = session.getCriteriaBuilder(); + JpaCriteriaQuery cq = cb.createQuery(C.class); + cq.from(C.class); + JpaCriteriaQuery bq = cb.createQuery(B.class); + bq.from(B.class); + + // This is how spring-data-jpa manage delete* Named queries + session.createQuery(cq).getResultList(); + List bs = session.createQuery(bq).getResultList(); + for (B b1 : bs) { + session.remove(b1); + } + }); + } +} +