From 6134678422e7c0b4372c97b403ac379d02b94bbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Westk=C3=A4mper?= Date: Wed, 24 Oct 2012 00:05:31 +0300 Subject: [PATCH] #258 optimized any() usage for entity collections --- .../query/jpa/JPQLCollectionAnyVisitor.java | 28 +++++++++++++------ .../jpa/JPQLCollectionAnyVisitorTest.java | 25 +++++++---------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLCollectionAnyVisitor.java b/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLCollectionAnyVisitor.java index 93315e438..9db829bd3 100644 --- a/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLCollectionAnyVisitor.java +++ b/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLCollectionAnyVisitor.java @@ -15,8 +15,11 @@ package com.mysema.query.jpa; import java.util.UUID; +import javax.persistence.Entity; + import com.mysema.query.support.CollectionAnyVisitor; import com.mysema.query.support.Context; +import com.mysema.query.types.EntityPath; import com.mysema.query.types.ExpressionUtils; import com.mysema.query.types.Ops; import com.mysema.query.types.Path; @@ -38,18 +41,25 @@ public final class JPQLCollectionAnyVisitor extends CollectionAnyVisitor { public static final JPQLCollectionAnyVisitor DEFAULT = new JPQLCollectionAnyVisitor(); @Override + @SuppressWarnings("all") protected Predicate exists(Context c, Predicate condition) { JPQLSubQuery query = new JPQLSubQuery(); for (int i = 0; i < c.paths.size(); i++) { - Path child = c.paths.get(i).getMetadata().getParent(); - Path parent = child.getMetadata().getParent(); - Path replacement = c.replacements.get(i); - String prefix = parent.accept(ToStringVisitor.DEFAULT, TEMPLATES).replace('.', '_'); - String suffix = UUID.randomUUID().toString().replace("-", "").substring(0,5); - EntityPathBase newParent = new EntityPathBase(parent.getType(), prefix + suffix); - Path newChild = new PathImpl(child.getType(), newParent, child.getMetadata().getExpression().toString()); - query.from(newParent).innerJoin(newChild, replacement); - query.where(ExpressionUtils.eq(newParent, parent)); + Path child = c.paths.get(i).getMetadata().getParent(); + EntityPath replacement = c.replacements.get(i); + if (c.paths.get(i).getType().isAnnotationPresent(Entity.class)) { + query.from(replacement); + query.where(new PredicateOperation(Ops.IN, replacement, child)); + } else { + // join via parent + Path parent = child.getMetadata().getParent(); + String prefix = parent.accept(ToStringVisitor.DEFAULT, TEMPLATES).replace('.', '_'); + String suffix = UUID.randomUUID().toString().replace("-", "").substring(0,5); + EntityPathBase newParent = new EntityPathBase(parent.getType(), prefix + suffix); + Path newChild = new PathImpl(child.getType(), newParent, child.getMetadata().getExpression().toString()); + query.from(newParent).innerJoin(newChild, replacement); + query.where(ExpressionUtils.eq(newParent, parent)); + } } c.clear(); query.where(condition); diff --git a/querydsl-jpa/src/test/java/com/mysema/query/jpa/JPQLCollectionAnyVisitorTest.java b/querydsl-jpa/src/test/java/com/mysema/query/jpa/JPQLCollectionAnyVisitorTest.java index 1955bfb54..6e9ccb487 100644 --- a/querydsl-jpa/src/test/java/com/mysema/query/jpa/JPQLCollectionAnyVisitorTest.java +++ b/querydsl-jpa/src/test/java/com/mysema/query/jpa/JPQLCollectionAnyVisitorTest.java @@ -43,30 +43,26 @@ public class JPQLCollectionAnyVisitorTest { public void Simple_BooleanOperation(){ Predicate predicate = cat.kittens.any().name.eq("Ruth123"); assertMatches("exists \\(select 1\n" + - "from Cat cat.*\n" + - " inner join cat.*.kittens as cat_kittens.*\n" + - "where cat.* = cat and cat_kittens.*.name = \\?1\\)", serialize(predicate)); + "from Cat cat_kittens.*\n" + + "where cat_kittens.* in elements\\(cat\\.kittens\\) and cat_kittens.*\\.name = \\?1\\)", serialize(predicate)); } @Test public void Simple_StringOperation(){ Predicate predicate = cat.kittens.any().name.substring(1).eq("uth123"); assertMatches("exists \\(select 1\n"+ - "from Cat cat.*\n"+ - " inner join cat.*.kittens as cat_kittens.*\n" + - "where cat.* = cat and substring\\(cat_kittens.*.name,2\\) = \\?1\\)", serialize(predicate)); + "from Cat cat_kittens.*\n" + + "where cat_kittens.* in elements\\(cat.kittens\\) and substring\\(cat_kittens.*\\.name,2\\) = \\?1\\)", serialize(predicate)); } @Test public void And_Operation(){ Predicate predicate = cat.kittens.any().name.eq("Ruth123").and(cat.kittens.any().bodyWeight.gt(10.0)); assertMatches("exists \\(select 1\n"+ - "from Cat cat.*\n"+ - " inner join cat.*.kittens as cat_kittens.*\n"+ - "where cat.* = cat and cat_kittens.*.name = \\?1\\) and exists \\(select 1\n" + - "from Cat cat.*\n" + - " inner join cat.*.kittens as cat_kittens.*\n" + - "where cat.* = cat and cat_kittens.*.bodyWeight > \\?2\\)", serialize(predicate)); + "from Cat cat_kittens.*\n" + + "where cat_kittens.* in elements\\(cat.kittens\\) and cat_kittens.*\\.name = \\?1\\) and exists \\(select 1\n" + + "from Cat cat_kittens.*\n" + + "where cat_kittens.* in elements\\(cat.kittens\\) and cat_kittens.*\\.bodyWeight > \\?2\\)", serialize(predicate)); } @Test @@ -74,9 +70,8 @@ public class JPQLCollectionAnyVisitorTest { Expression templateExpr = TemplateExpressionImpl.create(Boolean.class, "{0} = {1}", cat.kittens.any().name, ConstantImpl.create("Ruth123")); assertMatches("exists \\(select 1\n" + - "from Cat cat.*\n" + - " inner join cat.*.kittens as cat_kittens.*\n" + - "where cat.* = cat and cat_kittens.*.name = \\?1\\)", serialize(templateExpr)); + "from Cat cat_kittens.*\n" + + "where cat_kittens.* in elements\\(cat\\.kittens\\) and cat_kittens.*\\.name = \\?1\\)", serialize(templateExpr)); } private String serialize(Expression expression){