You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by jo...@apache.org on 2016/05/23 00:27:57 UTC
deltaspike git commit: DELTASPIKE-1152 Adding support for first and
top in method name, including docs.
Repository: deltaspike
Updated Branches:
refs/heads/master b02acc77e -> f632269f1
DELTASPIKE-1152 Adding support for first and top in method name, including docs.
Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/f632269f
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/f632269f
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/f632269f
Branch: refs/heads/master
Commit: f632269f12404626b0ae24b0fbf1c643b3aae8d9
Parents: b02acc7
Author: John D. Ament <jo...@apache.org>
Authored: Sun May 22 19:20:15 2016 -0400
Committer: John D. Ament <jo...@apache.org>
Committed: Sun May 22 20:28:00 2016 -0400
----------------------------------------------------------------------
.../impl/handler/CdiQueryInvocationContext.java | 2 +-
.../deltaspike/data/impl/meta/MethodPrefix.java | 81 +++++++++++---------
.../data/impl/meta/RepositoryMethod.java | 5 ++
.../deltaspike/data/impl/param/Parameters.java | 9 ++-
.../data/impl/handler/QueryHandlerTest.java | 33 +++++++-
.../data/impl/meta/MethodPrefixTest.java | 66 ++++++++++++++++
.../data/test/service/SimpleRepository.java | 4 +
documentation/src/main/asciidoc/data.adoc | 19 +++++
8 files changed, 175 insertions(+), 44 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f632269f/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
index 4505f6a..9f032e5 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
@@ -60,7 +60,7 @@ public class CdiQueryInvocationContext implements QueryInvocationContext
{
this.entityManager = entityManager;
this.args = args == null ? new Object[]{} : args;
- this.params = Parameters.create(method, this.args);
+ this.params = Parameters.create(method, this.args, repoMethod);
this.proxy = proxy;
this.method = method;
this.repoMethod = repoMethod;
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f632269f/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/MethodPrefix.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/MethodPrefix.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/MethodPrefix.java
index e421087..37f73b5 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/MethodPrefix.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/MethodPrefix.java
@@ -20,6 +20,9 @@ package org.apache.deltaspike.data.impl.meta;
import org.apache.deltaspike.data.api.SingleResultType;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
public class MethodPrefix
{
public static final String DEFAULT_PREFIX = "findBy";
@@ -28,13 +31,22 @@ public class MethodPrefix
public static final String DEFAULT_DELETE_PREFIX = "deleteBy";
public static final String DEFAULT_REMOVE_PREFIX = "removeBy";
+ private static final String FIND_FIRST_PREFIX = "find(First|Top)(\\d+)By";
+ private static final String FIND_FIRST_PREFIX_PATTERN = FIND_FIRST_PREFIX + "(.+)";
+ private static final Pattern DIGIT_PATTERN = Pattern.compile("\\d+");
+
private final String customPrefix;
private final String methodName;
+ private int definedMaxResults = 0;
public MethodPrefix(String customPrefix, String methodName)
{
this.customPrefix = customPrefix;
this.methodName = methodName;
+ if (this.methodName != null)
+ {
+ this.parseMaxResults();
+ }
}
public String removePrefix(String queryPart)
@@ -91,54 +103,46 @@ public class MethodPrefix
this.getPrefix().equalsIgnoreCase(DEFAULT_REMOVE_PREFIX);
}
- private static enum KnownQueryPrefix
+ public int getDefinedMaxResults()
{
- DEFAULT(DEFAULT_PREFIX)
- {
- @Override
- public SingleResultType getStyle()
- {
- return SingleResultType.JPA;
- }
- },
- OPTIONAL(DEFAULT_OPT_PREFIX)
- {
- @Override
- public SingleResultType getStyle()
- {
- return SingleResultType.OPTIONAL;
- }
- },
- ANY(DEFAULT_ANY_PREFIX)
+ return definedMaxResults;
+ }
+
+ private void parseMaxResults()
+ {
+ if (this.methodName.matches(FIND_FIRST_PREFIX_PATTERN))
{
- @Override
- public SingleResultType getStyle()
+ Matcher matcher = DIGIT_PATTERN.matcher(this.methodName);
+ if (matcher.find())
{
- return SingleResultType.ANY;
+ this.definedMaxResults = Integer.parseInt(matcher.group());
}
- },
- DELETE_DEFAULT(DEFAULT_DELETE_PREFIX)
+ }
+ }
+
+ private enum KnownQueryPrefix
+ {
+ DEFAULT(DEFAULT_PREFIX, SingleResultType.JPA),
+ FIND_FIRST(FIND_FIRST_PREFIX, SingleResultType.JPA)
{
@Override
- public SingleResultType getStyle()
+ public String removePrefix(String queryPart)
{
- return SingleResultType.ANY;
+ return queryPart.replaceFirst(FIND_FIRST_PREFIX,"");
}
},
- REMOVE_DEFAULT(DEFAULT_REMOVE_PREFIX)
- {
- @Override
- public SingleResultType getStyle()
- {
- return SingleResultType.ANY;
- }
- };
+ OPTIONAL(DEFAULT_OPT_PREFIX,SingleResultType.OPTIONAL),
+ ANY(DEFAULT_ANY_PREFIX, SingleResultType.ANY),
+ DELETE_DEFAULT(DEFAULT_DELETE_PREFIX, SingleResultType.ANY),
+ REMOVE_DEFAULT(DEFAULT_REMOVE_PREFIX, SingleResultType.ANY);
private final String prefix;
+ private final SingleResultType singleResultType;
- private KnownQueryPrefix(String prefix)
+ KnownQueryPrefix(String prefix, SingleResultType singleResultType)
{
this.prefix = prefix;
+ this.singleResultType = singleResultType;
}
public String removePrefix(String queryPart)
@@ -151,10 +155,17 @@ public class MethodPrefix
return prefix;
}
- public abstract SingleResultType getStyle();
+ public SingleResultType getStyle()
+ {
+ return this.singleResultType;
+ }
public static KnownQueryPrefix fromMethodName(String name)
{
+ if (name.matches(FIND_FIRST_PREFIX_PATTERN))
+ {
+ return FIND_FIRST;
+ }
for (KnownQueryPrefix mapping : values())
{
if (name.startsWith(mapping.getPrefix()))
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f632269f/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
index f56ffaf..08cedd8 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
@@ -223,6 +223,11 @@ public class RepositoryMethod
return mapper != null;
}
+ public int getDefinedMaxResults()
+ {
+ return this.methodPrefix.getDefinedMaxResults();
+ }
+
public SingleResultType getSingleResultStyle()
{
if (method.isAnnotationPresent(Query.class))
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f632269f/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/param/Parameters.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/param/Parameters.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/param/Parameters.java
index 76b8dae..d5e74b8 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/param/Parameters.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/param/Parameters.java
@@ -32,6 +32,7 @@ import org.apache.deltaspike.data.api.FirstResult;
import org.apache.deltaspike.data.api.MaxResults;
import org.apache.deltaspike.data.api.QueryParam;
import org.apache.deltaspike.data.api.mapping.QueryInOutMapper;
+import org.apache.deltaspike.data.impl.meta.RepositoryMethod;
/**
* Convenience class to manage method and query parameters.
@@ -61,9 +62,9 @@ public final class Parameters
return new Parameters(empty, DEFAULT_MAX, DEFAULT_FIRST);
}
- public static Parameters create(Method method, Object[] parameters)
+ public static Parameters create(Method method, Object[] parameters, RepositoryMethod repositoryMethod)
{
- int max = extractSizeRestriction(method);
+ int max = extractSizeRestriction(method, repositoryMethod);
int first = DEFAULT_FIRST;
List<Parameter> result = new ArrayList<Parameter>(parameters.length);
int paramIndex = 1;
@@ -142,13 +143,13 @@ public final class Parameters
return firstResult;
}
- private static int extractSizeRestriction(Method method)
+ private static int extractSizeRestriction(Method method, RepositoryMethod repositoryMethod)
{
if (method.isAnnotationPresent(org.apache.deltaspike.data.api.Query.class))
{
return method.getAnnotation(org.apache.deltaspike.data.api.Query.class).max();
}
- return 0;
+ return repositoryMethod.getDefinedMaxResults();
}
@SuppressWarnings("unchecked")
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f632269f/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/QueryHandlerTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/QueryHandlerTest.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/QueryHandlerTest.java
index 89b9397..f7b8ccd 100644
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/QueryHandlerTest.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/QueryHandlerTest.java
@@ -27,11 +27,8 @@ import static org.junit.Assert.assertTrue;
import java.util.List;
-import javax.enterprise.inject.Produces;
import javax.inject.Inject;
-import javax.persistence.EntityManager;
import javax.persistence.NonUniqueResultException;
-import javax.persistence.PersistenceContext;
import org.apache.deltaspike.data.test.TransactionalTestCase;
import org.apache.deltaspike.data.test.domain.Simple;
@@ -455,12 +452,40 @@ public class QueryHandlerTest extends TransactionalTestCase
builder.createSimple(name);
// when
- Simple result = repo.findByNameIgnoreCase("should_create_case_insensitive_query_for_equals");
+ Simple result = repo.findByNameIgnoreCase(name.toLowerCase());
// then
assertEquals(name, result.getName());
}
+ @Test
+ public void should_find_first_2()
+ {
+ final String name = "Should_Create_Case_Insensitive_Query_for_Equals";
+ builder.createSimple(name);
+ builder.createSimple(name);
+ builder.createSimple(name);
+ builder.createSimple("this is something else");
+
+ List<Simple> result = repo.findFirst2ByName(name);
+
+ assertEquals(2, result.size());
+ }
+
+ @Test
+ public void should_find_top_2()
+ {
+ final String name = "Should_Create_Case_Insensitive_Query_for_Equals";
+ builder.createSimple(name);
+ builder.createSimple(name);
+ builder.createSimple(name);
+ builder.createSimple("this is something else");
+
+ List<Simple> result = repo.findTop2ByName(name);
+
+ assertEquals(2, result.size());
+ }
+
@Before
public void setup()
{
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f632269f/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/meta/MethodPrefixTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/meta/MethodPrefixTest.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/meta/MethodPrefixTest.java
new file mode 100644
index 0000000..04e1aa1
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/meta/MethodPrefixTest.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.deltaspike.data.impl.meta;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class MethodPrefixTest
+{
+ @Test
+ public void shouldParseArbitraryMethodFindPrefix()
+ {
+ MethodPrefix methodPrefix = new MethodPrefix("","findTop20ByName");
+
+ String resultingQuery = methodPrefix.removePrefix("findTop20ByName");
+
+ assertEquals("Name", resultingQuery);
+ }
+
+ @Test
+ public void shouldParseFirst20MethodFindPrefix()
+ {
+ MethodPrefix methodPrefix = new MethodPrefix("","findFirst20ByName");
+
+ String resultingQuery = methodPrefix.removePrefix("findFirst20ByName");
+
+ assertEquals("Name", resultingQuery);
+ }
+
+ @Test
+ public void shouldParseDefinedMaxResults()
+ {
+ MethodPrefix methodPrefix = new MethodPrefix("","findFirst20ByName");
+
+ int maxResults = methodPrefix.getDefinedMaxResults();
+
+ assertEquals(20, maxResults);
+ }
+
+ @Test
+ public void shouldNotParseNonMatchingMethodName()
+ {
+ MethodPrefix methodPrefix = new MethodPrefix("","findAnyByName");
+
+ int maxResults = methodPrefix.getDefinedMaxResults();
+
+ assertEquals(0, maxResults);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f632269f/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleRepository.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleRepository.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleRepository.java
index ebadd20..62dcb24 100755
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleRepository.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleRepository.java
@@ -85,6 +85,10 @@ public abstract class SimpleRepository extends AbstractEntityRepository<Simple,
public abstract Simple findAnyByName(String name);
+ public abstract List<Simple> findFirst2ByName(String name);
+
+ public abstract List<Simple> findTop2ByName(String name);
+
public abstract List<Simple> findByOrderByCounterAscIdDesc();
@Query(value = "SELECT * from SIMPLE_TABLE s WHERE s.name = ?1", isNative = true)
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f632269f/documentation/src/main/asciidoc/data.adoc
----------------------------------------------------------------------
diff --git a/documentation/src/main/asciidoc/data.adoc b/documentation/src/main/asciidoc/data.adoc
index 6f7f76c..904a468 100644
--- a/documentation/src/main/asciidoc/data.adoc
+++ b/documentation/src/main/asciidoc/data.adoc
@@ -521,6 +521,25 @@ public interface PersonRepository extends EntityRepository<Person, Long>
}
------------------------------------------------------------------------------
+=== Query Limits
+
+Starting with Apache DeltaSpike 1.6.2, you can apply query limits using method
+expressions. They can be applied using `First` or `Top` keywords, in a method
+like this
+
+[source,java]
+------------------------------------------------------------------------------
+@Repository
+public interface PersonRepository extends EntityRepository<Person, Long>
+{
+
+ List<Person> findFirst2ByLastNameOrderByAgeAscLastNameDesc(String lastName);
+
+ List<Person> findTop2ByLastNameOrderByAgeAscLastNameDesc(String lastName);
+
+}
+------------------------------------------------------------------------------
+
=== Nested Properties
To create a comparison on a nested property, the traversal parts can be