From 32a9c398d30045ec0249f51b5a136ab0c5cb2a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Westk=C3=A4mper?= Date: Sun, 15 Feb 2015 13:32:12 +0200 Subject: [PATCH] Transform containsKey and containsValue via JPAMapAccessVisitor --- .../core/types/ParameterizedPathImpl.java | 36 ++++++++++++++++++ .../core/types/path/CollectionPath.java | 8 +--- .../querydsl/core/types/path/ListPath.java | 9 +---- .../com/querydsl/core/types/path/MapPath.java | 10 +---- .../com/querydsl/core/types/path/SetPath.java | 8 +--- .../java/com/querydsl/jpa/HQLTemplates.java | 18 --------- .../com/querydsl/jpa/JPAMapAccessVisitor.java | 24 +++++++++++- .../com/querydsl/jpa/AbstractJPATest.java | 6 --- .../java/com/querydsl/jpa/CollectionTest.java | 25 ++---------- .../java/com/querydsl/jpa/FeaturesTest.java | 2 +- .../com/querydsl/jpa/JPQLSerializerTest.java | 2 +- .../test/java/com/querydsl/jpa/MapTest.java | 38 ------------------- 12 files changed, 73 insertions(+), 113 deletions(-) create mode 100644 querydsl-core/src/main/java/com/querydsl/core/types/ParameterizedPathImpl.java delete mode 100644 querydsl-jpa/src/test/java/com/querydsl/jpa/MapTest.java diff --git a/querydsl-core/src/main/java/com/querydsl/core/types/ParameterizedPathImpl.java b/querydsl-core/src/main/java/com/querydsl/core/types/ParameterizedPathImpl.java new file mode 100644 index 000000000..63087c609 --- /dev/null +++ b/querydsl-core/src/main/java/com/querydsl/core/types/ParameterizedPathImpl.java @@ -0,0 +1,36 @@ +/* + * Copyright 2015, Timo Westkämper + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.querydsl.core.types; + +/** + * + * @param + */ +public class ParameterizedPathImpl extends PathImpl implements ParameterizedExpression { + + private static final long serialVersionUID = -498707460985111265L; + + private final Class[] parameterTypes; + + public ParameterizedPathImpl(Class type, PathMetadata metadata, Class... parameterTypes) { + super(type, metadata); + this.parameterTypes = parameterTypes; + } + + @Override + public Class getParameter(int index) { + return parameterTypes[index]; + } + +} diff --git a/querydsl-core/src/main/java/com/querydsl/core/types/path/CollectionPath.java b/querydsl-core/src/main/java/com/querydsl/core/types/path/CollectionPath.java index 296e7b739..652f50eea 100644 --- a/querydsl-core/src/main/java/com/querydsl/core/types/path/CollectionPath.java +++ b/querydsl-core/src/main/java/com/querydsl/core/types/path/CollectionPath.java @@ -18,11 +18,7 @@ import java.util.Collection; import javax.annotation.Nullable; -import com.querydsl.core.types.Path; -import com.querydsl.core.types.PathImpl; -import com.querydsl.core.types.PathMetadata; -import com.querydsl.core.types.PathMetadataFactory; -import com.querydsl.core.types.Visitor; +import com.querydsl.core.types.*; import com.querydsl.core.types.expr.SimpleExpression; /** @@ -60,7 +56,7 @@ public class CollectionPath> extends Co @SuppressWarnings("unchecked") public CollectionPath(Class type, Class queryType, PathMetadata metadata, PathInits inits) { - super(new PathImpl>((Class)Collection.class, metadata), inits); + super(new ParameterizedPathImpl>((Class)Collection.class, metadata, type), inits); this.elementType = (Class)type; this.queryType = queryType; this.pathMixin = (PathImpl>)mixin; diff --git a/querydsl-core/src/main/java/com/querydsl/core/types/path/ListPath.java b/querydsl-core/src/main/java/com/querydsl/core/types/path/ListPath.java index e8215a303..645744e65 100644 --- a/querydsl-core/src/main/java/com/querydsl/core/types/path/ListPath.java +++ b/querydsl-core/src/main/java/com/querydsl/core/types/path/ListPath.java @@ -20,12 +20,7 @@ import java.util.Map; import javax.annotation.Nullable; -import com.querydsl.core.types.Expression; -import com.querydsl.core.types.Path; -import com.querydsl.core.types.PathImpl; -import com.querydsl.core.types.PathMetadata; -import com.querydsl.core.types.PathMetadataFactory; -import com.querydsl.core.types.Visitor; +import com.querydsl.core.types.*; import com.querydsl.core.types.expr.ListExpression; import com.querydsl.core.types.expr.SimpleExpression; @@ -66,7 +61,7 @@ public class ListPath> extends Collecti @SuppressWarnings("unchecked") public ListPath(Class elementType, Class queryType, PathMetadata metadata, PathInits inits) { - super(new PathImpl>((Class)List.class, metadata), inits); + super(new ParameterizedPathImpl>((Class)List.class, metadata, elementType), inits); this.elementType = (Class)elementType; this.queryType = queryType; this.pathMixin = (PathImpl>)mixin; diff --git a/querydsl-core/src/main/java/com/querydsl/core/types/path/MapPath.java b/querydsl-core/src/main/java/com/querydsl/core/types/path/MapPath.java index f0475cdff..53b859881 100644 --- a/querydsl-core/src/main/java/com/querydsl/core/types/path/MapPath.java +++ b/querydsl-core/src/main/java/com/querydsl/core/types/path/MapPath.java @@ -20,13 +20,7 @@ import java.util.Map; import javax.annotation.Nullable; -import com.querydsl.core.types.Expression; -import com.querydsl.core.types.ExpressionException; -import com.querydsl.core.types.Path; -import com.querydsl.core.types.PathImpl; -import com.querydsl.core.types.PathMetadata; -import com.querydsl.core.types.PathMetadataFactory; -import com.querydsl.core.types.Visitor; +import com.querydsl.core.types.*; import com.querydsl.core.types.expr.MapExpressionBase; import com.querydsl.core.types.expr.SimpleExpression; @@ -63,7 +57,7 @@ public class MapPath> extends MapExp @SuppressWarnings("unchecked") public MapPath(Class keyType, Class valueType, Class queryType, PathMetadata metadata) { - super(new PathImpl>((Class)Map.class, metadata)); + super(new ParameterizedPathImpl>((Class)Map.class, metadata, keyType, valueType)); this.keyType = (Class) keyType; this.valueType = (Class) valueType; this.queryType = queryType; diff --git a/querydsl-core/src/main/java/com/querydsl/core/types/path/SetPath.java b/querydsl-core/src/main/java/com/querydsl/core/types/path/SetPath.java index 888ba5404..e7f9d76e1 100644 --- a/querydsl-core/src/main/java/com/querydsl/core/types/path/SetPath.java +++ b/querydsl-core/src/main/java/com/querydsl/core/types/path/SetPath.java @@ -18,11 +18,7 @@ import java.util.Set; import javax.annotation.Nullable; -import com.querydsl.core.types.Path; -import com.querydsl.core.types.PathImpl; -import com.querydsl.core.types.PathMetadata; -import com.querydsl.core.types.PathMetadataFactory; -import com.querydsl.core.types.Visitor; +import com.querydsl.core.types.*; import com.querydsl.core.types.expr.SimpleExpression; /** @@ -60,7 +56,7 @@ public class SetPath> extends Collectio @SuppressWarnings("unchecked") public SetPath(Class type, Class queryType, PathMetadata metadata, PathInits inits) { - super(new PathImpl>((Class)Set.class, metadata), inits); + super(new ParameterizedPathImpl>((Class)Set.class, metadata, type), inits); this.elementType = (Class)type; this.queryType = queryType; this.pathMixin = (PathImpl>)mixin; diff --git a/querydsl-jpa/src/main/java/com/querydsl/jpa/HQLTemplates.java b/querydsl-jpa/src/main/java/com/querydsl/jpa/HQLTemplates.java index 32ba444c8..08f7e4b42 100644 --- a/querydsl-jpa/src/main/java/com/querydsl/jpa/HQLTemplates.java +++ b/querydsl-jpa/src/main/java/com/querydsl/jpa/HQLTemplates.java @@ -23,7 +23,6 @@ import java.util.Map; import com.google.common.collect.ImmutableMap; import com.querydsl.core.types.Operator; import com.querydsl.core.types.Ops; -import com.querydsl.core.types.PathType; /** * HQLTemplates extends JPQLTemplates with Hibernate specific extensions @@ -75,23 +74,6 @@ public class HQLTemplates extends JPQLTemplates { builder.put(BigDecimal.class, "big_decimal"); typeNames = builder.build(); - // TODO : remove this when Hibernate supports member of properly - add(JPQLOps.MEMBER_OF, "{0} in elements({1})"); - add(JPQLOps.NOT_MEMBER_OF, "{0} not in elements({1})"); - - // path types - for (PathType type : new PathType[] { - PathType.LISTVALUE, - PathType.MAPVALUE, - PathType.MAPVALUE_CONSTANT }) { - add(type, "{0}[{1}]"); - } - add(PathType.LISTVALUE_CONSTANT, "{0}[{1s}]"); - add(PathType.COLLECTION_ANY, "any elements({0})"); - - add(Ops.CONTAINS_KEY, "{1} in indices({0})"); - add(Ops.CONTAINS_VALUE, "{1} in elements({0})"); - // add Hibernate Spatial mappings, if on classpath try { Class cl = Class.forName("com.querydsl.spatial.hibernate.HibernateSpatialSupport"); diff --git a/querydsl-jpa/src/main/java/com/querydsl/jpa/JPAMapAccessVisitor.java b/querydsl-jpa/src/main/java/com/querydsl/jpa/JPAMapAccessVisitor.java index 79e61f6ef..4d92a9ec2 100644 --- a/querydsl-jpa/src/main/java/com/querydsl/jpa/JPAMapAccessVisitor.java +++ b/querydsl-jpa/src/main/java/com/querydsl/jpa/JPAMapAccessVisitor.java @@ -21,6 +21,28 @@ class JPAMapAccessVisitor extends ReplaceVisitor { this.metadata = metadata; } + @Override + public Expression visit(Operation expr, @Nullable Void context) { + if (expr.getOperator() == Ops.CONTAINS_KEY) { + ParameterizedExpression map = (ParameterizedExpression) expr.getArg(0); + Expression key = expr.getArg(1); + Path replacement = new PathImpl(map.getParameter(1), + ExpressionUtils.createRootVariable((Path)map)); + metadata.addJoin(JoinType.LEFTJOIN, ExpressionUtils.as(map, replacement)); + metadata.addJoinCondition(ExpressionUtils.eq( + Expressions.operation(map.getParameter(0), JPQLOps.KEY, replacement), + key)); + return ExpressionUtils.isNotNull(replacement); + } else if (expr.getOperator() == Ops.CONTAINS_VALUE) { + ParameterizedExpression map = (ParameterizedExpression) expr.getArg(0); + Expression value = expr.getArg(1); + return Expressions.predicate(JPQLOps.MEMBER_OF, value, map); + } else { + return super.visit(expr, context); + } + } + + @Override public Expression visit(Path expr, @Nullable Void context) { expr = (Path) super.visit(expr, null); PathMetadata pathMetadata = expr.getMetadata(); @@ -33,7 +55,7 @@ class JPAMapAccessVisitor extends ReplaceVisitor { ParameterizedExpression parExpr = (ParameterizedExpression) parent; replacement = new PathImpl(parExpr.getParameter(1), ExpressionUtils.createRootVariable(parent)); - metadata.addJoin(JoinType.JOIN, ExpressionUtils.as(parent, replacement)); + metadata.addJoin(JoinType.LEFTJOIN, ExpressionUtils.as(parent, replacement)); metadata.addJoinCondition(ExpressionUtils.eq( Expressions.operation(parExpr.getParameter(0), JPQLOps.KEY, replacement), ExpressionUtils.toExpression(pathMetadata.getElement()))); diff --git a/querydsl-jpa/src/test/java/com/querydsl/jpa/AbstractJPATest.java b/querydsl-jpa/src/test/java/com/querydsl/jpa/AbstractJPATest.java index 19f7cfb99..52afbbf4d 100644 --- a/querydsl-jpa/src/test/java/com/querydsl/jpa/AbstractJPATest.java +++ b/querydsl-jpa/src/test/java/com/querydsl/jpa/AbstractJPATest.java @@ -907,42 +907,36 @@ public abstract class AbstractJPATest { } @Test - @NoEclipseLink @NoOpenJPA @NoBatooJPA public void Map_ContainsKey() { QShow show = QShow.show; assertEquals(1l, query().from(show).where(show.acts.containsKey("a")).count()); } @Test - @NoEclipseLink @NoOpenJPA @NoBatooJPA public void Map_ContainsKey2() { QShow show = QShow.show; assertEquals(1l, query().from(show).where(show.acts.containsKey("b")).count()); } @Test - @NoEclipseLink @NoOpenJPA @NoBatooJPA public void Map_ContainsKey3() { QShow show = QShow.show; assertEquals(0l, query().from(show).where(show.acts.containsKey("c")).count()); } @Test - @NoEclipseLink @NoOpenJPA @NoBatooJPA public void Map_ContainsValue() { QShow show = QShow.show; assertEquals(1l, query().from(show).where(show.acts.containsValue("A")).count()); } @Test - @NoEclipseLink @NoOpenJPA @NoBatooJPA public void Map_ContainsValue2() { QShow show = QShow.show; assertEquals(1l, query().from(show).where(show.acts.containsValue("B")).count()); } @Test - @NoEclipseLink @NoOpenJPA @NoBatooJPA public void Map_ContainsValue3() { QShow show = QShow.show; assertEquals(0l, query().from(show).where(show.acts.containsValue("C")).count()); diff --git a/querydsl-jpa/src/test/java/com/querydsl/jpa/CollectionTest.java b/querydsl-jpa/src/test/java/com/querydsl/jpa/CollectionTest.java index 64ee710bf..ab865e4d0 100644 --- a/querydsl-jpa/src/test/java/com/querydsl/jpa/CollectionTest.java +++ b/querydsl-jpa/src/test/java/com/querydsl/jpa/CollectionTest.java @@ -21,39 +21,22 @@ public class CollectionTest extends AbstractQueryTest{ @Test public void Constant_InElements_Set() { - assertToString("?1 in elements(cat.kittensSet)", cat.kittensSet.contains(new Cat())); + assertToString("?1 member of cat.kittensSet", cat.kittensSet.contains(new Cat())); } @Test public void Constant_InElements_List() { - assertToString("?1 in elements(cat.kittens)", cat.kittens.contains(new Cat())); + assertToString("?1 member of cat.kittens", cat.kittens.contains(new Cat())); } @Test public void Path_InElements_List() { - assertToString("cat in elements(cat1.kittens)", cat.in(cat1.kittens)); + assertToString("cat member of cat1.kittens", cat.in(cat1.kittens)); } @Test public void Path_InElements_Set() { - assertToString("cat in elements(cat1.kittensSet)", cat.in(cat1.kittensSet)); + assertToString("cat member of cat1.kittensSet", cat.in(cat1.kittensSet)); } - - @Test - public void CollectionOperations() { - // HQL functions that take collection-valued path expressions: size(), - // minelement(), maxelement(), minindex(), maxindex(), along with the - // special elements() and indices functions which may be quantified - // using some, all, exists, any, in. - cat.kittens.size(); -// minelement(cat.kittens); -// maxelement(cat.kittens); -// minindex(cat.kittens); -// maxindex(cat.kittens); - assertToString("cat.kittens[0]", cat.kittens(0)); - assertToString("cat.kittens[0]", cat.kittens.get(0)); - - // some, all, exists, any, in. - } } diff --git a/querydsl-jpa/src/test/java/com/querydsl/jpa/FeaturesTest.java b/querydsl-jpa/src/test/java/com/querydsl/jpa/FeaturesTest.java index 5faeca5c8..11942dbd0 100644 --- a/querydsl-jpa/src/test/java/com/querydsl/jpa/FeaturesTest.java +++ b/querydsl-jpa/src/test/java/com/querydsl/jpa/FeaturesTest.java @@ -129,7 +129,7 @@ public class FeaturesTest extends AbstractQueryTest { // toString("cat.bodyWeight as bw", cat.bodyWeight.as("bw")); - assertToString("kitten in elements(cat.kittens)", kitten.in(cat.kittens)); + assertToString("kitten member of cat.kittens", kitten.in(cat.kittens)); // toString("distinct cat.bodyWeight", distinct(cat.bodyWeight)); } diff --git a/querydsl-jpa/src/test/java/com/querydsl/jpa/JPQLSerializerTest.java b/querydsl-jpa/src/test/java/com/querydsl/jpa/JPQLSerializerTest.java index ce25d6812..71efdf2e4 100644 --- a/querydsl-jpa/src/test/java/com/querydsl/jpa/JPQLSerializerTest.java +++ b/querydsl-jpa/src/test/java/com/querydsl/jpa/JPQLSerializerTest.java @@ -154,7 +154,7 @@ public class JPQLSerializerTest { serializer.serializeForDelete(md); assertEquals("delete from Cat kitten\n" + "where kitten.id = ?1 and exists (select 1\n" + - "from Cat cat\nwhere cat.id = ?2 and kitten in elements(cat.kittens))", serializer.toString()); + "from Cat cat\nwhere cat.id = ?2 and kitten member of cat.kittens)", serializer.toString()); } @Test diff --git a/querydsl-jpa/src/test/java/com/querydsl/jpa/MapTest.java b/querydsl-jpa/src/test/java/com/querydsl/jpa/MapTest.java deleted file mode 100644 index bce1c6dea..000000000 --- a/querydsl-jpa/src/test/java/com/querydsl/jpa/MapTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2011, Mysema Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.querydsl.jpa; - -import org.junit.Test; - -import com.querydsl.jpa.domain.QShow; - -public class MapTest extends AbstractQueryTest { - - private QShow show = QShow.show; - - @Test - public void Contains() { - assertToString("show.acts[?1] = ?2", show.acts.contains("x", "y")); - } - - @Test - public void Contains_Key() { - assertToString("?1 in indices(show.acts)", show.acts.containsKey("x")); - } - - @Test - public void Contains_Value() { - assertToString("?1 in elements(show.acts)", show.acts.containsValue("y")); - } -}