#258 optimized any() usage for entity collections

This commit is contained in:
Timo Westkämper 2012-10-24 00:05:31 +03:00
parent cc5718341a
commit 6134678422
2 changed files with 29 additions and 24 deletions

View File

@ -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);

View File

@ -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<Boolean> 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){