-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15818 from DavideD/15814-Lazy-fetch
Lazy fetch associations with Hibernate Reactive
- Loading branch information
Showing
6 changed files
with
300 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
79 changes: 79 additions & 0 deletions
79
...a/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointFetchLazy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package io.quarkus.it.hibernate.reactive.postgresql; | ||
|
||
import java.util.Collection; | ||
import java.util.concurrent.CompletionStage; | ||
|
||
import javax.inject.Inject; | ||
import javax.ws.rs.GET; | ||
import javax.ws.rs.POST; | ||
import javax.ws.rs.Path; | ||
import javax.ws.rs.PathParam; | ||
|
||
import org.hibernate.reactive.mutiny.Mutiny; | ||
import org.hibernate.reactive.stage.Stage; | ||
|
||
import io.quarkus.it.hibernate.reactive.postgresql.lazy.Author; | ||
import io.quarkus.it.hibernate.reactive.postgresql.lazy.Book; | ||
import io.smallrye.mutiny.Uni; | ||
import io.vertx.mutiny.pgclient.PgPool; | ||
import io.vertx.mutiny.sqlclient.Tuple; | ||
|
||
@Path("/hr-fetch") | ||
public class HibernateReactiveTestEndpointFetchLazy { | ||
|
||
@Inject | ||
Mutiny.Session mutinySession; | ||
|
||
// I'm using the factory because there are some issues with an injected Stage.Session | ||
// See issue https://github.com/quarkusio/quarkus/issues/14812 | ||
@Inject | ||
Stage.SessionFactory stageSessionFactory; | ||
|
||
// Injecting a Vert.x Pool is not required, It's used to | ||
// independently validate the contents of the database for the test | ||
@Inject | ||
PgPool pgPool; | ||
|
||
@GET | ||
@Path("/findBooksWithMutiny/{authorId}") | ||
public Uni<Collection<Book>> findBooksWithMutiny(@PathParam("authorId") Integer authorId) { | ||
return mutinySession.find(Author.class, authorId) | ||
.chain(author -> Mutiny.fetch(author.getBooks())); | ||
} | ||
|
||
@GET | ||
@Path("/findBooksWithStage/{authorId}") | ||
public CompletionStage<Collection<Book>> findBooksWithStage(@PathParam("authorId") Integer authorId) { | ||
return stageSessionFactory.withTransaction((session, tx) -> session | ||
.find(Author.class, authorId) | ||
.thenCompose(author -> Stage.fetch(author.getBooks()))); | ||
} | ||
|
||
@POST | ||
@Path("/prepareDb") | ||
public Uni<String> prepareDb() { | ||
final Author author = new Author(567, "Neal Stephenson"); | ||
final Book book1 = new Book("0-380-97346-4", "Cryptonomicon", author); | ||
final Book book2 = new Book("0-553-08853-X", "Snow Crash", author); | ||
author.getBooks().add(book1); | ||
author.getBooks().add(book2); | ||
|
||
return mutinySession.createQuery(" delete from Book").executeUpdate() | ||
.call(() -> mutinySession.createQuery("delete from Author").executeUpdate()) | ||
.call(() -> mutinySession.persist(author)) | ||
.chain(mutinySession::flush) | ||
.chain(() -> selectNameFromId(author.getId())); | ||
} | ||
|
||
private Uni<String> selectNameFromId(Integer id) { | ||
return pgPool.preparedQuery("SELECT name FROM Author WHERE id = $1").execute(Tuple.of(id)).map(rowSet -> { | ||
if (rowSet.size() == 1) { | ||
return rowSet.iterator().next().getString(0); | ||
} else if (rowSet.size() > 1) { | ||
throw new AssertionError("More than one result returned: " + rowSet.size()); | ||
} else { | ||
return null; // Size 0 | ||
} | ||
}); | ||
} | ||
} |
73 changes: 73 additions & 0 deletions
73
...ive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/lazy/Author.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package io.quarkus.it.hibernate.reactive.postgresql.lazy; | ||
|
||
import static javax.persistence.CascadeType.PERSIST; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.Objects; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.Id; | ||
import javax.persistence.OneToMany; | ||
import javax.persistence.Table; | ||
|
||
@Entity | ||
@Table | ||
public class Author { | ||
@Id | ||
private Integer id; | ||
|
||
private String name; | ||
|
||
@OneToMany(mappedBy = "author", cascade = PERSIST) | ||
private Collection<Book> books = new ArrayList<>(); | ||
|
||
public Author() { | ||
} | ||
|
||
public Author(Integer id, String name) { | ||
this.id = id; | ||
this.name = name; | ||
} | ||
|
||
public Integer getId() { | ||
return id; | ||
} | ||
|
||
public void setId(Integer id) { | ||
this.id = id; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
|
||
public Collection<Book> getBooks() { | ||
return books; | ||
} | ||
|
||
public void setBooks(Collection<Book> books) { | ||
this.books = books; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) { | ||
return true; | ||
} | ||
if (o == null || getClass() != o.getClass()) { | ||
return false; | ||
} | ||
Author author = (Author) o; | ||
return Objects.equals(name, author.name); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(name); | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
...ctive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/lazy/Book.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package io.quarkus.it.hibernate.reactive.postgresql.lazy; | ||
|
||
import static javax.persistence.FetchType.LAZY; | ||
|
||
import java.util.Objects; | ||
|
||
import javax.json.bind.annotation.JsonbTransient; | ||
import javax.persistence.Entity; | ||
import javax.persistence.GeneratedValue; | ||
import javax.persistence.Id; | ||
import javax.persistence.ManyToOne; | ||
import javax.persistence.Table; | ||
|
||
@Entity | ||
@Table | ||
public class Book { | ||
@Id | ||
@GeneratedValue | ||
private Integer id; | ||
|
||
private String isbn; | ||
|
||
private String title; | ||
|
||
@JsonbTransient | ||
@ManyToOne(fetch = LAZY) | ||
private Author author; | ||
|
||
public Book(String isbn, String title, Author author) { | ||
this.title = title; | ||
this.isbn = isbn; | ||
this.author = author; | ||
} | ||
|
||
public Book() { | ||
} | ||
|
||
public Integer getId() { | ||
return id; | ||
} | ||
|
||
public void setId(Integer id) { | ||
this.id = id; | ||
} | ||
|
||
public String getIsbn() { | ||
return isbn; | ||
} | ||
|
||
public void setIsbn(String isbn) { | ||
this.isbn = isbn; | ||
} | ||
|
||
public String getTitle() { | ||
return title; | ||
} | ||
|
||
public void setTitle(String title) { | ||
this.title = title; | ||
} | ||
|
||
public Author getAuthor() { | ||
return author; | ||
} | ||
|
||
public void setAuthor(Author author) { | ||
this.author = author; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) { | ||
return true; | ||
} | ||
if (o == null || getClass() != o.getClass()) { | ||
return false; | ||
} | ||
Book book = (Book) o; | ||
return Objects.equals(isbn, book.isbn) | ||
&& Objects.equals(title, book.title); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(isbn, title); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
...java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveFetchLazyInGraalIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package io.quarkus.it.hibernate.reactive.postgresql; | ||
|
||
import io.quarkus.test.junit.NativeImageTest; | ||
|
||
@NativeImageTest | ||
public class HibernateReactiveFetchLazyInGraalIT extends HibernateReactiveFetchLazyTest { | ||
} |
53 changes: 53 additions & 0 deletions
53
...test/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveFetchLazyTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package io.quarkus.it.hibernate.reactive.postgresql; | ||
|
||
import static java.util.Arrays.asList; | ||
import static java.util.stream.Collectors.toList; | ||
import static org.hamcrest.Matchers.is; | ||
import static org.junit.jupiter.api.Assertions.assertIterableEquals; | ||
|
||
import java.util.List; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import io.quarkus.test.common.http.TestHTTPEndpoint; | ||
import io.quarkus.test.junit.QuarkusTest; | ||
import io.restassured.RestAssured; | ||
import io.restassured.response.Response; | ||
|
||
@QuarkusTest | ||
@TestHTTPEndpoint(HibernateReactiveTestEndpointFetchLazy.class) | ||
public class HibernateReactiveFetchLazyTest { | ||
|
||
@Test | ||
public void fetchAfterFindWithMutiny() { | ||
RestAssured.when() | ||
.post("/prepareDb") | ||
.then() | ||
.body(is("Neal Stephenson")); | ||
|
||
Response response = RestAssured.when() | ||
.get("/findBooksWithMutiny/567") | ||
.then() | ||
.extract().response(); | ||
assertTitles(response, "Cryptonomicon", "Snow Crash"); | ||
} | ||
|
||
@Test | ||
public void fetchAfterFindWithWithStage() { | ||
RestAssured.when() | ||
.post("/prepareDb") | ||
.then() | ||
.body(is("Neal Stephenson")); | ||
|
||
Response response = RestAssured.when() | ||
.get("/findBooksWithStage/567") | ||
.then() | ||
.extract().response(); | ||
assertTitles(response, "Cryptonomicon", "Snow Crash"); | ||
} | ||
|
||
private void assertTitles(Response response, String... expectedTitles) { | ||
List<Object> titles = response.jsonPath().getList("title").stream().sorted().collect(toList()); | ||
assertIterableEquals(asList(expectedTitles), titles); | ||
} | ||
} |