Merge pull request #9034 from kkaravitis/master
[BAEL-3936] Constructing a JPA query between unrelated entities
This commit is contained in:
		
						commit
						09e9f0ce0b
					
				| @ -48,6 +48,17 @@ | |||||||
|             <version>${postgres.version}</version> |             <version>${postgres.version}</version> | ||||||
|             <scope>runtime</scope> |             <scope>runtime</scope> | ||||||
|         </dependency> |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>com.querydsl</groupId> | ||||||
|  |             <artifactId>querydsl-apt</artifactId> | ||||||
|  |             <version>${querydsl.version}</version> | ||||||
|  |             <scope>provided</scope> | ||||||
|  |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>com.querydsl</groupId> | ||||||
|  |             <artifactId>querydsl-jpa</artifactId> | ||||||
|  |             <version>${querydsl.version}</version> | ||||||
|  |         </dependency> | ||||||
| 
 | 
 | ||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>org.assertj</groupId> |             <groupId>org.assertj</groupId> | ||||||
| @ -101,16 +112,33 @@ | |||||||
|                         <configuration> |                         <configuration> | ||||||
|                             <sources> |                             <sources> | ||||||
|                                 <source>target/metamodel</source> |                                 <source>target/metamodel</source> | ||||||
|  |                                 <source>${project.build.directory}/generated-sources/java/</source> | ||||||
|                             </sources> |                             </sources> | ||||||
|                         </configuration> |                         </configuration> | ||||||
|                     </execution> |                     </execution> | ||||||
|                 </executions> |                 </executions> | ||||||
|             </plugin> |             </plugin> | ||||||
|  |             <plugin> | ||||||
|  |                 <groupId>com.mysema.maven</groupId> | ||||||
|  |                 <artifactId>apt-maven-plugin</artifactId> | ||||||
|  |                 <version>1.1.3</version> | ||||||
|  |                 <executions> | ||||||
|  |                     <execution> | ||||||
|  |                         <goals> | ||||||
|  |                             <goal>process</goal> | ||||||
|  |                         </goals> | ||||||
|  |                         <configuration> | ||||||
|  |                             <outputDirectory>target/generated-sources/java</outputDirectory> | ||||||
|  |                             <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor> | ||||||
|  |                         </configuration> | ||||||
|  |                     </execution> | ||||||
|  |                 </executions> | ||||||
|  |             </plugin> | ||||||
|         </plugins> |         </plugins> | ||||||
|     </build> |     </build> | ||||||
| 
 | 
 | ||||||
|     <properties> |     <properties> | ||||||
|         <hibernate.version>5.4.0.Final</hibernate.version> |         <hibernate.version>5.4.14.Final</hibernate.version> | ||||||
|         <eclipselink.version>2.7.4</eclipselink.version> |         <eclipselink.version>2.7.4</eclipselink.version> | ||||||
|         <postgres.version>42.2.5</postgres.version> |         <postgres.version>42.2.5</postgres.version> | ||||||
|         <javax.persistence-api.version>2.2</javax.persistence-api.version> |         <javax.persistence-api.version>2.2</javax.persistence-api.version> | ||||||
| @ -118,6 +146,7 @@ | |||||||
|         <maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version> |         <maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version> | ||||||
|         <maven-processor-plugin.version>3.3.3</maven-processor-plugin.version> |         <maven-processor-plugin.version>3.3.3</maven-processor-plugin.version> | ||||||
|         <build-helper-maven-plugin.version>3.0.0</build-helper-maven-plugin.version> |         <build-helper-maven-plugin.version>3.0.0</build-helper-maven-plugin.version> | ||||||
|  |         <querydsl.version>4.3.1</querydsl.version> | ||||||
|     </properties> |     </properties> | ||||||
| 
 | 
 | ||||||
| </project> | </project> | ||||||
|  | |||||||
| @ -0,0 +1,90 @@ | |||||||
|  | package com.baeldung.jpa.unrelated.entities; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.annotations.Fetch; | ||||||
|  | import org.hibernate.annotations.FetchMode; | ||||||
|  | import org.hibernate.annotations.NotFound; | ||||||
|  | import org.hibernate.annotations.NotFoundAction; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.*; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Objects; | ||||||
|  | 
 | ||||||
|  | @Entity | ||||||
|  | @Table(name = "menu") | ||||||
|  | public class Cocktail { | ||||||
|  |     @Id | ||||||
|  |     @Column(name = "cocktail_name") | ||||||
|  |     private String name; | ||||||
|  | 
 | ||||||
|  |     @Column | ||||||
|  |     private double price; | ||||||
|  | 
 | ||||||
|  |     @Column(name = "category") | ||||||
|  |     private String category; | ||||||
|  | 
 | ||||||
|  |     @OneToOne | ||||||
|  |     @NotFound(action = NotFoundAction.IGNORE) | ||||||
|  |     @JoinColumn(name = "cocktail_name", | ||||||
|  |         referencedColumnName = "cocktail",  | ||||||
|  |         insertable = false, updatable = false,  | ||||||
|  |         foreignKey = @javax.persistence | ||||||
|  |           .ForeignKey(value = ConstraintMode.NO_CONSTRAINT)) | ||||||
|  |     private Recipe recipe; | ||||||
|  | 
 | ||||||
|  |     @OneToMany(fetch = FetchType.LAZY) | ||||||
|  |     @NotFound(action = NotFoundAction.IGNORE) | ||||||
|  |     @JoinColumn( | ||||||
|  |         name = "cocktail",  | ||||||
|  |         referencedColumnName = "cocktail_name",  | ||||||
|  |         insertable = false,  | ||||||
|  |         updatable = false,  | ||||||
|  |         foreignKey = @javax.persistence | ||||||
|  |           .ForeignKey(value = ConstraintMode.NO_CONSTRAINT)) | ||||||
|  |     private List<MultipleRecipe> recipeList; | ||||||
|  | 
 | ||||||
|  |     public Cocktail() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Cocktail(String name, double price, String baseIngredient) { | ||||||
|  |         this.name = name; | ||||||
|  |         this.price = price; | ||||||
|  |         this.category = baseIngredient; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getName() { | ||||||
|  |         return name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public double getPrice() { | ||||||
|  |         return price; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getCategory() { | ||||||
|  |         return category; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Recipe getRecipe() { | ||||||
|  |         return recipe; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public List<MultipleRecipe> getRecipeList() { | ||||||
|  |         return recipeList; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean equals(Object o) { | ||||||
|  |         if (this == o) | ||||||
|  |             return true; | ||||||
|  |         if (o == null || getClass() != o.getClass()) | ||||||
|  |             return false; | ||||||
|  |         Cocktail cocktail = (Cocktail) o; | ||||||
|  |         return Double.compare(cocktail.price, price) == 0 &&  | ||||||
|  |             Objects.equals(name, cocktail.name) &&  | ||||||
|  |             Objects.equals(category, cocktail.category); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int hashCode() { | ||||||
|  |         return Objects.hash(name, price, category); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,71 @@ | |||||||
|  | package com.baeldung.jpa.unrelated.entities; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.Column; | ||||||
|  | import javax.persistence.Entity; | ||||||
|  | import javax.persistence.Id; | ||||||
|  | import javax.persistence.Table; | ||||||
|  | import java.util.Objects; | ||||||
|  | 
 | ||||||
|  | @Entity | ||||||
|  | @Table(name = "multiple_recipes") | ||||||
|  | public class MultipleRecipe { | ||||||
|  |     @Id | ||||||
|  |     @Column(name = "id") | ||||||
|  |     private Long id; | ||||||
|  | 
 | ||||||
|  |     @Column(name = "cocktail") | ||||||
|  |     private String cocktail; | ||||||
|  | 
 | ||||||
|  |     @Column(name = "instructions") | ||||||
|  |     private String instructions; | ||||||
|  | 
 | ||||||
|  |     @Column(name = "base_ingredient") | ||||||
|  |     private String baseIngredient; | ||||||
|  | 
 | ||||||
|  |     public MultipleRecipe() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public MultipleRecipe(Long id, String cocktail,  | ||||||
|  |         String instructions, String baseIngredient) { | ||||||
|  |         this.id = id; | ||||||
|  |         this.cocktail = cocktail; | ||||||
|  |         this.instructions = instructions; | ||||||
|  |         this.baseIngredient = baseIngredient; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Long getId() { | ||||||
|  |         return id; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getCocktail() { | ||||||
|  |         return cocktail; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getInstructions() { | ||||||
|  |         return instructions; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getBaseIngredient() { | ||||||
|  |         return baseIngredient; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean equals(Object o) { | ||||||
|  |         if (this == o) | ||||||
|  |             return true; | ||||||
|  |         if (o == null || getClass() != o.getClass()) | ||||||
|  |             return false; | ||||||
|  |         MultipleRecipe that = (MultipleRecipe) o; | ||||||
|  |          | ||||||
|  |         return Objects.equals(id, that.id) &&  | ||||||
|  |           Objects.equals(cocktail, that.cocktail) &&  | ||||||
|  |           Objects.equals(instructions, that.instructions) &&  | ||||||
|  |           Objects.equals(baseIngredient, that.baseIngredient); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int hashCode() { | ||||||
|  |         return Objects.hash(id, cocktail,  | ||||||
|  |           instructions, baseIngredient); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,50 @@ | |||||||
|  | package com.baeldung.jpa.unrelated.entities; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.Column; | ||||||
|  | import javax.persistence.Entity; | ||||||
|  | import javax.persistence.Id; | ||||||
|  | import javax.persistence.Table; | ||||||
|  | import java.util.Objects; | ||||||
|  | 
 | ||||||
|  | @Entity | ||||||
|  | @Table(name="recipes") | ||||||
|  | public class Recipe { | ||||||
|  |     @Id | ||||||
|  |     @Column(name = "cocktail") | ||||||
|  |     private String cocktail; | ||||||
|  | 
 | ||||||
|  |     @Column | ||||||
|  |     private String instructions; | ||||||
|  | 
 | ||||||
|  |     public Recipe() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Recipe(String cocktail, String instructions) { | ||||||
|  |         this.cocktail = cocktail; | ||||||
|  |         this.instructions = instructions; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getCocktail() { | ||||||
|  |         return cocktail; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getInstructions() { | ||||||
|  |         return instructions; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean equals(Object o) { | ||||||
|  |         if (this == o) | ||||||
|  |             return true; | ||||||
|  |         if (o == null || getClass() != o.getClass()) | ||||||
|  |             return false; | ||||||
|  |         Recipe recipe = (Recipe) o; | ||||||
|  |         return Objects.equals(cocktail, recipe.cocktail)  | ||||||
|  |           && Objects.equals(instructions, recipe.instructions); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int hashCode() { | ||||||
|  |         return Objects.hash(cocktail, instructions); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -162,5 +162,26 @@ | |||||||
|                       value="false" /> |                       value="false" /> | ||||||
|         </properties> |         </properties> | ||||||
|     </persistence-unit> |     </persistence-unit> | ||||||
| 
 |      | ||||||
| </persistence> |     <persistence-unit name="jpa-h2-unrelated-entities"> | ||||||
|  |         <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> | ||||||
|  |         <class>com.baeldung.jpa.unrelated.entities.Cocktail</class> | ||||||
|  | 		<class>com.baeldung.jpa.unrelated.entities.Recipe</class> | ||||||
|  | 		<class>com.baeldung.jpa.unrelated.entities.MultipleRecipe</class> | ||||||
|  |         <exclude-unlisted-classes>true</exclude-unlisted-classes> | ||||||
|  |         <properties> | ||||||
|  |             <property name="javax.persistence.jdbc.driver" | ||||||
|  |                       value="org.h2.Driver" /> | ||||||
|  |             <property name="javax.persistence.jdbc.url" | ||||||
|  |                       value="jdbc:h2:mem:test" /> | ||||||
|  |             <property name="javax.persistence.jdbc.user" value="sa" /> | ||||||
|  |             <property name="javax.persistence.jdbc.password" value="" /> | ||||||
|  |             <property name="hibernate.dialect" | ||||||
|  |                       value="org.hibernate.dialect.H2Dialect" /> | ||||||
|  |             <property name="hibernate.hbm2ddl.auto" value="create" /> | ||||||
|  |             <property name="show_sql" value="true" /> | ||||||
|  |             <property name="hibernate.temp.use_jdbc_metadata_defaults" | ||||||
|  |                       value="false" /> | ||||||
|  |         </properties> | ||||||
|  |     </persistence-unit> | ||||||
|  | </persistence> | ||||||
|  | |||||||
| @ -0,0 +1,189 @@ | |||||||
|  | package com.baeldung.jpa.unrelated.entities; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.*; | ||||||
|  | 
 | ||||||
|  | import com.querydsl.jpa.impl.JPAQuery; | ||||||
|  | import org.junit.jupiter.api.*; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.function.Consumer; | ||||||
|  | 
 | ||||||
|  | import static org.junit.jupiter.api.Assertions.*; | ||||||
|  | 
 | ||||||
|  | public class UnrelatedEntitiesUnitTest { | ||||||
|  |     private static EntityManagerFactory entityManagerFactory; | ||||||
|  |     private static EntityManager entityManager; | ||||||
|  |     private static Cocktail mojito; | ||||||
|  |     private static Cocktail ginTonic; | ||||||
|  | 
 | ||||||
|  |     @BeforeAll | ||||||
|  |     public static void setup() { | ||||||
|  |         entityManagerFactory = Persistence.createEntityManagerFactory("jpa-h2-unrelated-entities"); | ||||||
|  |         entityManager = entityManagerFactory.createEntityManager(); | ||||||
|  |         mojito = new Cocktail("Mojito", 11, "Rum"); | ||||||
|  |         ginTonic = new Cocktail("Gin tonic", 8.50, "Gin"); | ||||||
|  |         entityManager.getTransaction().begin(); | ||||||
|  |         entityManager.persist(mojito); | ||||||
|  |         entityManager.persist(ginTonic); | ||||||
|  |         entityManager.persist(new Recipe(mojito.getName(), "Some instructions")); | ||||||
|  |         entityManager.persist(new MultipleRecipe(1L, mojito.getName(),  | ||||||
|  |           "some instructions", mojito.getCategory())); | ||||||
|  |         entityManager.persist(new MultipleRecipe(2L, mojito.getName(),  | ||||||
|  |           "some other instructions", mojito.getCategory())); | ||||||
|  |         entityManager.getTransaction().commit(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @AfterAll | ||||||
|  |     public static void closeSession() { | ||||||
|  |         entityManager.close(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenCocktailsWithRecipe_whenQuerying_thenTheExpectedCocktailsReturned() { | ||||||
|  |         // JPA | ||||||
|  |         Cocktail cocktail = entityManager.createQuery("select c " | ||||||
|  |           + "from Cocktail c join c.recipe", Cocktail.class) | ||||||
|  |           .getSingleResult(); | ||||||
|  |         verifyResult(mojito, cocktail); | ||||||
|  | 
 | ||||||
|  |         cocktail = entityManager.createQuery("select c " | ||||||
|  |           + "from Cocktail c join Recipe r " | ||||||
|  |           + "on c.name = r.cocktail", Cocktail.class) | ||||||
|  |           .getSingleResult(); | ||||||
|  |         verifyResult(mojito, cocktail); | ||||||
|  | 
 | ||||||
|  |         // QueryDSL | ||||||
|  |         cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail) | ||||||
|  |           .join(QCocktail.cocktail.recipe) | ||||||
|  |           .fetchOne(); | ||||||
|  |         verifyResult(mojito, cocktail); | ||||||
|  | 
 | ||||||
|  |         cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail) | ||||||
|  |           .join(QRecipe.recipe) | ||||||
|  |           .on(QCocktail.cocktail.name.eq(QRecipe.recipe.cocktail)) | ||||||
|  |           .fetchOne(); | ||||||
|  |         verifyResult(mojito, cocktail); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenCocktailsWithoutRecipe_whenQuerying_thenTheExpectedCocktailsReturned() { | ||||||
|  |         Cocktail cocktail = entityManager.createQuery("select c " | ||||||
|  |           + "from Cocktail c left join c.recipe r "  | ||||||
|  |           + "where r is null", Cocktail.class) | ||||||
|  |           .getSingleResult(); | ||||||
|  |         verifyResult(ginTonic, cocktail); | ||||||
|  | 
 | ||||||
|  |         cocktail = entityManager.createQuery("select c " | ||||||
|  |           + "from Cocktail c left join Recipe r "  | ||||||
|  |           + "on c.name = r.cocktail "  | ||||||
|  |           + "where r is null", Cocktail.class) | ||||||
|  |           .getSingleResult(); | ||||||
|  |         verifyResult(ginTonic, cocktail); | ||||||
|  | 
 | ||||||
|  |         QRecipe recipe = new QRecipe("alias"); | ||||||
|  |         cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail) | ||||||
|  |           .leftJoin(QCocktail.cocktail.recipe, recipe) | ||||||
|  |           .where(recipe.isNull()) | ||||||
|  |           .fetchOne(); | ||||||
|  |         verifyResult(ginTonic, cocktail); | ||||||
|  | 
 | ||||||
|  |         cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail) | ||||||
|  |           .leftJoin(QRecipe.recipe) | ||||||
|  |           .on(QCocktail.cocktail.name.eq(QRecipe.recipe.cocktail)) | ||||||
|  |           .where(QRecipe.recipe.isNull()) | ||||||
|  |           .fetchOne(); | ||||||
|  |         verifyResult(ginTonic, cocktail); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenCocktailsWithMultipleRecipes_whenQuerying_thenTheExpectedCocktailsReturned() { | ||||||
|  |         // JPQL | ||||||
|  |         Cocktail cocktail = entityManager.createQuery("select c " | ||||||
|  |           + "from Cocktail c join c.recipeList", Cocktail.class) | ||||||
|  |           .getSingleResult(); | ||||||
|  |         verifyResult(mojito, cocktail); | ||||||
|  | 
 | ||||||
|  |         cocktail = entityManager.createQuery("select c " | ||||||
|  |           + "from Cocktail c join MultipleRecipe mr " | ||||||
|  |           + "on mr.cocktail = c.name", Cocktail.class) | ||||||
|  |           .getSingleResult(); | ||||||
|  |         verifyResult(mojito, cocktail); | ||||||
|  | 
 | ||||||
|  |         // QueryDSL | ||||||
|  |         cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail) | ||||||
|  |           .join(QCocktail.cocktail.recipeList) | ||||||
|  |           .fetchOne(); | ||||||
|  |         verifyResult(mojito, cocktail); | ||||||
|  | 
 | ||||||
|  |         cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail) | ||||||
|  |           .join(QMultipleRecipe.multipleRecipe) | ||||||
|  |           .on(QCocktail.cocktail.name.eq(QMultipleRecipe.multipleRecipe.cocktail)) | ||||||
|  |           .fetchOne(); | ||||||
|  |         verifyResult(mojito, cocktail); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenCocktailsWithoutMultipleRecipes_whenQuerying_thenTheExpectedCocktailsReturned() { | ||||||
|  |         // JPQL | ||||||
|  |         Cocktail cocktail = entityManager.createQuery("select c " | ||||||
|  |           + "from Cocktail c left join c.recipeList r " | ||||||
|  |           + "where r is null", Cocktail.class) | ||||||
|  |           .getSingleResult(); | ||||||
|  |         verifyResult(ginTonic, cocktail); | ||||||
|  | 
 | ||||||
|  |         cocktail = entityManager.createQuery("select c " | ||||||
|  |           + "from Cocktail c left join MultipleRecipe r "  | ||||||
|  |           + "on c.name = r.cocktail " | ||||||
|  |           + "where r is null", Cocktail.class) | ||||||
|  |           .getSingleResult(); | ||||||
|  |         verifyResult(ginTonic, cocktail); | ||||||
|  | 
 | ||||||
|  |         // QueryDSL | ||||||
|  |         QMultipleRecipe multipleRecipe = new QMultipleRecipe("alias"); | ||||||
|  |         cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail) | ||||||
|  |           .leftJoin(QCocktail.cocktail.recipeList, multipleRecipe) | ||||||
|  |           .where(multipleRecipe.isNull()) | ||||||
|  |           .fetchOne(); | ||||||
|  |         verifyResult(ginTonic, cocktail); | ||||||
|  | 
 | ||||||
|  |         cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail) | ||||||
|  |           .leftJoin(QMultipleRecipe.multipleRecipe) | ||||||
|  |           .on(QCocktail.cocktail.name.eq(QMultipleRecipe.multipleRecipe.cocktail)) | ||||||
|  |           .where(QMultipleRecipe.multipleRecipe.isNull()) | ||||||
|  |           .fetchOne(); | ||||||
|  |         verifyResult(ginTonic, cocktail); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenMultipleRecipesWithCocktails_whenQuerying_thenTheExpectedMultipleRecipesReturned() { | ||||||
|  |         Consumer<List<MultipleRecipe>> verifyResult = recipes -> { | ||||||
|  |             assertEquals(2, recipes.size()); | ||||||
|  |             recipes.forEach(r -> assertEquals(mojito.getName(), r.getCocktail())); | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         // JPQL | ||||||
|  |         List<MultipleRecipe> recipes = entityManager.createQuery("select distinct r " | ||||||
|  |           + "from MultipleRecipe r " | ||||||
|  |           + "join Cocktail c "  | ||||||
|  |           + "on r.baseIngredient = c.category", | ||||||
|  |           MultipleRecipe.class).getResultList(); | ||||||
|  |          | ||||||
|  |         verifyResult.accept(recipes); | ||||||
|  | 
 | ||||||
|  |         // QueryDSL | ||||||
|  |         QCocktail cocktail = QCocktail.cocktail; | ||||||
|  |         QMultipleRecipe multipleRecipe = QMultipleRecipe.multipleRecipe; | ||||||
|  |         recipes = new JPAQuery<MultipleRecipe>(entityManager).from(multipleRecipe) | ||||||
|  |           .join(cocktail) | ||||||
|  |           .on(multipleRecipe.baseIngredient.eq(cocktail.category)) | ||||||
|  |           .fetch(); | ||||||
|  |          | ||||||
|  |         verifyResult.accept(recipes); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void verifyResult(Cocktail expectedCocktail, Cocktail queryResult) { | ||||||
|  |         assertNotNull(queryResult); | ||||||
|  |         assertEquals(expectedCocktail, queryResult); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user