From e5a78f0ee507f146d04d7c1b59fef57f75ed20a8 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Tue, 9 Nov 2021 13:41:41 +0100 Subject: [PATCH 1/4] Add test exclusion property handling to jakarta module --- hibernate-core-jakarta/hibernate-core-jakarta.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hibernate-core-jakarta/hibernate-core-jakarta.gradle b/hibernate-core-jakarta/hibernate-core-jakarta.gradle index b83db47504..09e3e1bd5d 100644 --- a/hibernate-core-jakarta/hibernate-core-jakarta.gradle +++ b/hibernate-core-jakarta/hibernate-core-jakarta.gradle @@ -279,6 +279,12 @@ test { } maxHeapSize = '3G' + // Allow to exclude specific tests + if (project.hasProperty('excludeTests')) { + filter { + excludeTestsMatching project.property('excludeTests').toString() + } + } } From 76eeb6fb5e5421bca80a908ced6eca944f750474 Mon Sep 17 00:00:00 2001 From: "nathan.xu" Date: Fri, 12 Nov 2021 21:04:15 -0500 Subject: [PATCH 2/4] HHH-14926 fix ascii error in 'test-case-guide.adoc' --- test-case-guide.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-case-guide.adoc b/test-case-guide.adoc index 1f4a8b6185..eb46249163 100644 --- a/test-case-guide.adoc +++ b/test-case-guide.adoc @@ -9,7 +9,7 @@ This is meant as a guide for writing test cases to be attached to bug reports in There are a number of tenants that make up a good test case as opposed to a poor one. In fact there are a few guides for this across the web including (http://stackoverflow.com/help/mcve[MCVE]) and (http://sscce.org/[SSCCE]). These guides all assert the same ideas albeit using different terms. Given the ubiquity of StackOverflow and the fact that the MCVE guidelines were written specifically for StackOverflow, we will use those terms here as we assume most developers have seen them before: * (M)inimal - Provide just the minimal information needed. If second level caching is irrelevant to the bug report then the test should not use second level caching. If entity inheritance is irrelevant then do not use it in the test. If your application uses Spring Data, remove Spring Data from the test. -* (C)omplete - Provide all information needed to reproduce the problem. If a bug only occurs when using bytecode enhancement, then the test should include bytecode enhancement. In other words the test should be self-contained. +* \(C)omplete - Provide all information needed to reproduce the problem. If a bug only occurs when using bytecode enhancement, then the test should include bytecode enhancement. In other words the test should be self-contained. * (V)erifiable - The test should actually reproduce the problem being reported. From 1a641695fa48ae1eb4b545a6eac36152f50e4038 Mon Sep 17 00:00:00 2001 From: Ratul sharker Date: Sun, 14 Nov 2021 17:43:21 +0600 Subject: [PATCH 3/4] HHH-14916 : inside `renderFetches`, `renderJoins` called if the `fetch` is `instanceof` `Form` interface. --- .../hibernate/query/criteria/internal/QueryStructure.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/QueryStructure.java b/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/QueryStructure.java index e4bddf4a54..e0a88f871e 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/QueryStructure.java +++ b/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/QueryStructure.java @@ -19,6 +19,7 @@ import javax.persistence.criteria.AbstractQuery; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Fetch; +import javax.persistence.criteria.From; import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.ParameterExpression; @@ -483,6 +484,11 @@ private void renderFetches( .append( ( (FromImplementor) fetch ).renderTableExpression( renderingContext ) ); renderFetches( jpaqlQuery, renderingContext, fetch.getFetches() ); + + if (fetch instanceof From) { + From from = (From) fetch; + renderJoins(jpaqlQuery, renderingContext, from.getJoins()); + } } } } From b125d13edea4c330bfcfa2681360aebb59aeabd0 Mon Sep 17 00:00:00 2001 From: Ratul sharker Date: Sun, 14 Nov 2021 17:48:19 +0600 Subject: [PATCH 4/4] HHH-14916 : test case written. --- .../criteria/internal/hhh14916/Author.java | 25 +++++++ .../criteria/internal/hhh14916/Book.java | 32 ++++++++ .../criteria/internal/hhh14916/Chapter.java | 22 ++++++ .../internal/hhh14916/HHH14916Test.java | 74 +++++++++++++++++++ 4 files changed, 153 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/Author.java create mode 100644 hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/Book.java create mode 100644 hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/Chapter.java create mode 100644 hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/HHH14916Test.java diff --git a/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/Author.java b/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/Author.java new file mode 100644 index 0000000000..a37b0910a2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/Author.java @@ -0,0 +1,25 @@ +package org.hibernate.query.criteria.internal.hhh14916; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; + +@Entity +public class Author { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + public Long authorId; + + @Column + public String name; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "author", orphanRemoval = true, cascade = CascadeType.ALL) + public List books = new ArrayList<>(); +} diff --git a/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/Book.java b/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/Book.java new file mode 100644 index 0000000000..23ec689a03 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/Book.java @@ -0,0 +1,32 @@ +package org.hibernate.query.criteria.internal.hhh14916; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; + +@Entity +public class Book { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + public Long bookId; + + @Column + public String name; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "author_id", nullable = false) + public Author author; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "book", orphanRemoval = true, cascade = CascadeType.ALL) + public List chapters = new ArrayList<>(); +} diff --git a/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/Chapter.java b/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/Chapter.java new file mode 100644 index 0000000000..a97d6da843 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/Chapter.java @@ -0,0 +1,22 @@ +package org.hibernate.query.criteria.internal.hhh14916; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +@Entity +public class Chapter { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + public Long chapterId; + + public String name; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "book_id", nullable = false) + public Book book; +} diff --git a/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/HHH14916Test.java b/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/HHH14916Test.java new file mode 100644 index 0000000000..3583194b83 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/hhh14916/HHH14916Test.java @@ -0,0 +1,74 @@ +package org.hibernate.query.criteria.internal.hhh14916; + +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.testing.TestForIssue; +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.JoinType; +import javax.persistence.criteria.ListJoin; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +@TestForIssue( jiraKey = "HHH-14916" ) +public class HHH14916Test extends BaseEntityManagerFunctionalTestCase { + + @Before + public void before() { + populateData(); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Author.class, Book.class, Chapter.class }; + } + + @Test + public void testJoinOnFetchNoExceptionThrow() { + doInJPA( this::entityManagerFactory, entityManager -> { + + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery query = builder.createQuery(Author.class); + + final Root root = query.from(Author.class); + final ListJoin authorBookJoin = (ListJoin)root.fetch("books", JoinType.LEFT); + + final ListJoin bookChapterJoin = authorBookJoin.joinList("chapters", JoinType.LEFT); + + final Predicate finalPredicate = builder.equal(bookChapterJoin.get("name"), "Overview of HTTP"); + query.where(finalPredicate); + + Author author = entityManager.createQuery(query).getSingleResult(); + + assertEquals(author.name, "David Gourley"); + assertEquals(author.books.get(0).name, "HTTP Definitive guide"); + assertEquals(author.books.get(0).chapters.get(0).name, "Overview of HTTP"); + } ); + } + + public void populateData() { + doInJPA(this::entityManagerFactory, entityManager -> { + // Insert data + Chapter chapter = new Chapter(); + chapter.name = "Overview of HTTP"; + + Book book = new Book(); + book.name = "HTTP Definitive guide"; + + Author author = new Author(); + author.name = "David Gourley"; + + book.chapters.add(chapter); + author.books.add(book); + + chapter.book = book; + book.author = author; + + entityManager.persist(author); + }); + } +}