From 65efa9b45661e21f0f93f1a1da7db18169a2aba0 Mon Sep 17 00:00:00 2001 From: Graham Cox Date: Thu, 10 Sep 2026 09:16:35 +0100 Subject: [PATCH 1/3] BAEL-7152: The @Find Annotation in Hibernate --- .../hibernate-queries-3/pom.xml | 66 +++++++++++ .../com/baeldung/hibernate/find/Author.java | 23 ++++ .../hibernate/find/AuthorRepository.java | 9 ++ .../com/baeldung/hibernate/find/Book.java | 27 +++++ .../hibernate/find/BookRepository.java | 41 +++++++ .../baeldung/hibernate/find/FindUnitTest.java | 111 ++++++++++++++++++ .../resources/find/hibernate.find.cfg.xml | 16 +++ .../src/test/resources/find/init.sql | 26 ++++ pom.xml | 2 + 9 files changed, 321 insertions(+) create mode 100644 persistence-modules/hibernate-queries-3/pom.xml create mode 100644 persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Author.java create mode 100644 persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/AuthorRepository.java create mode 100644 persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Book.java create mode 100644 persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/BookRepository.java create mode 100644 persistence-modules/hibernate-queries-3/src/test/java/com/baeldung/hibernate/find/FindUnitTest.java create mode 100644 persistence-modules/hibernate-queries-3/src/test/resources/find/hibernate.find.cfg.xml create mode 100644 persistence-modules/hibernate-queries-3/src/test/resources/find/init.sql diff --git a/persistence-modules/hibernate-queries-3/pom.xml b/persistence-modules/hibernate-queries-3/pom.xml new file mode 100644 index 000000000000..26c8e3845776 --- /dev/null +++ b/persistence-modules/hibernate-queries-3/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + hibernate-queries-3 + 0.0.1-SNAPSHOT + hibernate-queries-3 + + + com.baeldung + persistence-modules + 1.0.0-SNAPSHOT + + + + + org.hibernate.orm + hibernate-core + ${hibernate.version} + + + jakarta.data + jakarta.data-api + ${jakarta-data.version} + + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation.version} + + + com.h2database + h2 + ${h2.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + org.hibernate.orm + hibernate-processor + ${hibernate.version} + + + + + + + + + 2.1.214 + 7.4.6.Final + 1.0.2 + 2.1.1 + + + diff --git a/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Author.java b/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Author.java new file mode 100644 index 000000000000..938f505b9758 --- /dev/null +++ b/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Author.java @@ -0,0 +1,23 @@ +package com.baeldung.hibernate.find; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(name = "authors") +public class Author { + @Id + @Column(name = "author_id") + private Long authorId; + private String name; + + public Long getAuthorId() { + return authorId; + } + + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/AuthorRepository.java b/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/AuthorRepository.java new file mode 100644 index 000000000000..dc404cd25d31 --- /dev/null +++ b/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/AuthorRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.hibernate.find; + +import jakarta.data.repository.Repository; +import jakarta.persistence.EntityManager; + +@Repository +public interface AuthorRepository { + EntityManager entityManager(); +} diff --git a/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Book.java b/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Book.java new file mode 100644 index 000000000000..476c84c2b9c5 --- /dev/null +++ b/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Book.java @@ -0,0 +1,27 @@ +package com.baeldung.hibernate.find; + +import jakarta.persistence.*; + +@Entity +@Table(name = "books") +public class Book { + @Id + @Column(name = "book_id") + private Long bookId; + private String title; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "author_id", nullable = false) + private Author author; + + public Long getBookId() { + return bookId; + } + + public String getTitle() { + return title; + } + + public Author getAuthor() { + return author; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/BookRepository.java b/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/BookRepository.java new file mode 100644 index 000000000000..92d57c0ce7ce --- /dev/null +++ b/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/BookRepository.java @@ -0,0 +1,41 @@ +package com.baeldung.hibernate.find; + +import java.util.List; +import java.util.Optional; + +import jakarta.annotation.Nullable; +import jakarta.data.Order; +import jakarta.data.page.Page; +import jakarta.data.page.PageRequest; +import jakarta.data.repository.OrderBy; +import jakarta.data.repository.Repository; +import org.hibernate.annotations.processing.Find; + +@Repository +public interface BookRepository { + @Find + @OrderBy(value = "title", descending = true) + @OrderBy("author$name") + List getAllBooks(); + + @Find + List getAllBooks(Order sort); + + @Find + @OrderBy("title") + Page getBooksPage(PageRequest pageRequest); + + @Find + Book getBookWithTitle(String title); + + @Find + Optional getOptionalBookWithTitle(String title); + + @Find + @Nullable + Book getNullableBookWithTitle(String title); + + @Find + List getAllBooksByAuthorName(String author$name); + +} diff --git a/persistence-modules/hibernate-queries-3/src/test/java/com/baeldung/hibernate/find/FindUnitTest.java b/persistence-modules/hibernate-queries-3/src/test/java/com/baeldung/hibernate/find/FindUnitTest.java new file mode 100644 index 000000000000..7fcb689fe6ff --- /dev/null +++ b/persistence-modules/hibernate-queries-3/src/test/java/com/baeldung/hibernate/find/FindUnitTest.java @@ -0,0 +1,111 @@ +package com.baeldung.hibernate.find; + +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import jakarta.data.Order; +import jakarta.data.Sort; +import jakarta.data.exceptions.EmptyResultException; +import jakarta.data.page.Page; +import jakarta.data.page.PageRequest; +import org.hibernate.SessionFactory; +import org.hibernate.StatelessSession; +import org.hibernate.cfg.Configuration; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class FindUnitTest { + + private static SessionFactory sessionFactory; + private StatelessSession session; + + @BeforeAll + static void createSession() { + sessionFactory = new Configuration() + .addAnnotatedClass(Author.class) + .addAnnotatedClass(Book.class) + .configure("find/hibernate.find.cfg.xml") + .buildSessionFactory(); + } + + @BeforeEach + void before() { + session = sessionFactory.openStatelessSession(); + } + + @AfterEach + void after() { + session.close(); + } + + @Test + void whenListingAllBooks_thenAllBooksAreReturned() { + BookRepository_ repository = new BookRepository_(session); + List books = repository.getAllBooks(); + + assertEquals(7, books.size()); + } + + @Test + void whenGettingASingleBook_thenThebookIsReturned() { + BookRepository_ repository = new BookRepository_(session); + Book book = repository.getBookWithTitle("Animal Farm"); + + assertEquals("Animal Farm", book.getTitle()); + assertEquals(102L, book.getBookId()); + } + + @Test + void whenGettingAnUnknownBook_thenNothingIsReturned() { + BookRepository_ repository = new BookRepository_(session); + + assertThrows(EmptyResultException.class, () -> repository.getBookWithTitle("Unknown Book")); + + assertEquals(Optional.empty(), repository.getOptionalBookWithTitle("Unknown Book")); + assertNull(repository.getNullableBookWithTitle("Unknown Book")); + } + + @Test + void whenListingBooksByAuthor_thenAllBooksAreReturned() { + BookRepository_ repository = new BookRepository_(session); + List books = repository.getAllBooksByAuthorName("George Orwell"); + + assertEquals(2, books.size()); + } + + @Test + void whenListingBooksInOrder_thenTheCorrectBooksAreReturned() { + BookRepository_ repository = new BookRepository_(session); + List books = repository.getAllBooks(Order.by( + Sort.asc("title"), + Sort.desc("author.name") + )); + + assertEquals(7, books.size()); + assertEquals(101L, books.get(0).getBookId()); + assertEquals(107L, books.get(6).getBookId()); + } + + @Test + void whenListingPagesOfBooks_thenTheCorrectBooksAreReturned() { + BookRepository_ repository = new BookRepository_(session); + Page books = repository.getBooksPage(PageRequest.ofPage(1, 3, true)); + + assertEquals(3, books.content().size()); + assertEquals(101L, books.content().get(0).getBookId()); + assertEquals(102L, books.content().get(2).getBookId()); + + assertEquals(7L, books.totalElements()); + assertTrue(books.hasNext()); + assertFalse(books.hasPrevious()); + } + +} diff --git a/persistence-modules/hibernate-queries-3/src/test/resources/find/hibernate.find.cfg.xml b/persistence-modules/hibernate-queries-3/src/test/resources/find/hibernate.find.cfg.xml new file mode 100644 index 000000000000..4354878ef50a --- /dev/null +++ b/persistence-modules/hibernate-queries-3/src/test/resources/find/hibernate.find.cfg.xml @@ -0,0 +1,16 @@ + + + + + + org.hibernate.dialect.H2Dialect + jdbc:h2:mem:find;MODE=MySQL;INIT=RUNSCRIPT FROM 'classpath:find/init.sql' + org.h2.Driver + sa + + validate + true + + + \ No newline at end of file diff --git a/persistence-modules/hibernate-queries-3/src/test/resources/find/init.sql b/persistence-modules/hibernate-queries-3/src/test/resources/find/init.sql new file mode 100644 index 000000000000..42eb43c2e56d --- /dev/null +++ b/persistence-modules/hibernate-queries-3/src/test/resources/find/init.sql @@ -0,0 +1,26 @@ +CREATE TABLE authors ( + author_id BIGINT PRIMARY KEY, + name TEXT NOT NULL +); + +CREATE TABLE books ( + book_id BIGINT PRIMARY KEY, + title TEXT NOT NULL, + author_id BIGINT NOT NULL, + FOREIGN KEY (author_id) REFERENCES authors(author_id) +); + +INSERT INTO authors (author_id, name) VALUES + (1, 'George Orwell'), + (2, 'Haruki Murakami'), + (3, 'Agatha Christie'), +(4, 'Ursula K. Le Guin'); + +INSERT INTO books (book_id, title, author_id) VALUES + (101, '1984', 1), + (102, 'Animal Farm', 1), + (103, 'Norwegian Wood', 2), + (104, 'Kafka on the Shore', 2), + (105, 'Murder on the Orient Express', 3), + (106, 'And Then There Were None', 3), + (107, 'The Left Hand of Darkness', 4); \ No newline at end of file diff --git a/pom.xml b/pom.xml index 295a443236f2..d8cd2e8afaca 100644 --- a/pom.xml +++ b/pom.xml @@ -1693,6 +1693,7 @@ spring-cloud-modules/spring-cloud-task/springcloudtaskbatch aspectj persistence-modules/hibernate-queries-2 + persistence-modules/hibernate-queries-3 testing-modules/selenium-3/scrollelementintoview testing-modules/selenium-3/selenium-json-demo @@ -1762,6 +1763,7 @@ spring-cloud-modules/spring-cloud-task/springcloudtaskbatch aspectj persistence-modules/hibernate-queries-2 + persistence-modules/hibernate-queries-3 testing-modules/selenium-3/scrollelementintoview testing-modules/selenium-3/selenium-json-demo codenameone From ff4dc03ed3264a02162bcc9a9407781fcc4e0f65 Mon Sep 17 00:00:00 2001 From: Graham Cox Date: Tue, 15 Sep 2026 07:17:46 +0100 Subject: [PATCH 2/3] Added blank lines between fields --- .../src/main/java/com/baeldung/hibernate/find/Author.java | 1 + .../src/main/java/com/baeldung/hibernate/find/Book.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Author.java b/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Author.java index 938f505b9758..ee5b2443b36b 100644 --- a/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Author.java +++ b/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Author.java @@ -11,6 +11,7 @@ public class Author { @Id @Column(name = "author_id") private Long authorId; + private String name; public Long getAuthorId() { diff --git a/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Book.java b/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Book.java index 476c84c2b9c5..4ed04aae02ef 100644 --- a/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Book.java +++ b/persistence-modules/hibernate-queries-3/src/main/java/com/baeldung/hibernate/find/Book.java @@ -8,7 +8,9 @@ public class Book { @Id @Column(name = "book_id") private Long bookId; + private String title; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "author_id", nullable = false) private Author author; From 4c1d61ae2ba1ca24ec10e25c1b62dab406d20f86 Mon Sep 17 00:00:00 2001 From: Liam Williams Date: Tue, 15 Sep 2026 12:01:06 +0100 Subject: [PATCH 3/3] Update persistence-modules/hibernate-queries-3/src/test/resources/find/init.sql --- .../hibernate-queries-3/src/test/resources/find/init.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/hibernate-queries-3/src/test/resources/find/init.sql b/persistence-modules/hibernate-queries-3/src/test/resources/find/init.sql index 42eb43c2e56d..6a05b8158153 100644 --- a/persistence-modules/hibernate-queries-3/src/test/resources/find/init.sql +++ b/persistence-modules/hibernate-queries-3/src/test/resources/find/init.sql @@ -14,7 +14,7 @@ INSERT INTO authors (author_id, name) VALUES (1, 'George Orwell'), (2, 'Haruki Murakami'), (3, 'Agatha Christie'), -(4, 'Ursula K. Le Guin'); + (4, 'Ursula K. Le Guin'); INSERT INTO books (book_id, title, author_id) VALUES (101, '1984', 1),