You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by th...@apache.org on 2013/11/28 15:48:09 UTC

[1/3] git commit: DELTASPIKE-448 Refactoring of exception handling

Updated Branches:
  refs/heads/master feba6a764 -> c3f89b2fc


DELTASPIKE-448 Refactoring of exception handling


Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/4e8d5831
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/4e8d5831
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/4e8d5831

Branch: refs/heads/master
Commit: 4e8d58316ee707cda093fe24eb1c6b6286b90d04
Parents: f3c00d8
Author: Thomas Hug <Th...@ctp-consulting.com>
Authored: Fri Nov 22 17:52:30 2013 +0100
Committer: Thomas Hug <Th...@ctp-consulting.com>
Committed: Thu Nov 28 14:38:25 2013 +0100

----------------------------------------------------------------------
 .../data/api/QueryInvocationException.java      | 71 +++++++++++++++++++
 .../data/spi/QueryInvocationContext.java        | 12 ++++
 .../data/impl/builder/DelegateQueryBuilder.java | 13 +++-
 .../impl/handler/CdiQueryInvocationContext.java |  7 ++
 .../impl/handler/QueryInvocationException.java  | 72 --------------------
 .../data/impl/handler/EntityManagerTest.java    |  1 +
 .../data/impl/handler/QueryHandlerTest.java     |  5 +-
 .../data/test/util/TestDeployments.java         |  4 +-
 8 files changed, 108 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4e8d5831/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryInvocationException.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryInvocationException.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryInvocationException.java
new file mode 100644
index 0000000..1e870c2
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryInvocationException.java
@@ -0,0 +1,71 @@
+/*
+ * 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.api;
+
+import java.lang.reflect.Method;
+
+import org.apache.deltaspike.data.spi.QueryInvocationContext;
+
+public class QueryInvocationException extends RuntimeException
+{
+
+    private static final long serialVersionUID = 1L;
+
+    public QueryInvocationException(Throwable t, QueryInvocationContext context)
+    {
+        super(createMessage(context, t), t);
+    }
+
+    public QueryInvocationException(String message, QueryInvocationContext context)
+    {
+        super(createMessage(context));
+    }
+
+    public QueryInvocationException(Throwable t, Class<?> proxy, Method method)
+    {
+        super(createMessage(proxy, method, t), t);
+    }
+
+    private static String createMessage(QueryInvocationContext context)
+    {
+        StringBuilder builder = new StringBuilder();
+        builder.append("Failed calling Repository: [");
+        builder.append("Repository=").append(context.getRepositoryClass().getName()).append(",");
+        builder.append("entity=").append(context.getEntityClass().getName()).append(",");
+        builder.append("method=").append(context.getMethod().getName()).append(",");
+        return builder.toString();
+    }
+
+    private static String createMessage(QueryInvocationContext context, Throwable t)
+    {
+        StringBuilder builder = new StringBuilder(createMessage(context));
+        builder.append("exception=").append(t.getClass()).append(",message=").append(t.getMessage());
+        return builder.toString();
+    }
+
+    private static String createMessage(Class<?> repoClass, Method method, Throwable t)
+    {
+        StringBuilder builder = new StringBuilder();
+        builder.append("Exception calling Repository: [");
+        builder.append("Repository=").append(repoClass).append(",");
+        builder.append("method=").append(method.getName()).append("],");
+        builder.append("exception=").append(t.getClass()).append(",message=").append(t.getMessage());
+        return builder.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4e8d5831/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/QueryInvocationContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/QueryInvocationContext.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/QueryInvocationContext.java
index 6ee4836..c533ba9 100644
--- a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/QueryInvocationContext.java
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/QueryInvocationContext.java
@@ -18,6 +18,8 @@
  */
 package org.apache.deltaspike.data.spi;
 
+import java.lang.reflect.Method;
+
 import javax.persistence.EntityManager;
 
 /**
@@ -44,4 +46,14 @@ public interface QueryInvocationContext
      */
     boolean isNew(Object entity);
 
+    /**
+     * The type of the repository currently accessed.
+     */
+    Class<?> getRepositoryClass();
+
+    /**
+     * The repository method currently executed.
+     */
+    Method getMethod();
+
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4e8d5831/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java
index 8ed2361..0668ce7 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java
@@ -27,10 +27,11 @@ import javax.enterprise.context.spi.CreationalContext;
 import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.inject.Inject;
+import javax.persistence.PersistenceException;
 
 import org.apache.deltaspike.core.api.provider.BeanProvider;
+import org.apache.deltaspike.data.api.QueryInvocationException;
 import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
-import org.apache.deltaspike.data.impl.handler.QueryInvocationException;
 import org.apache.deltaspike.data.impl.meta.MethodType;
 import org.apache.deltaspike.data.impl.meta.QueryInvocation;
 import org.apache.deltaspike.data.impl.util.bean.BeanDestroyable;
@@ -53,6 +54,10 @@ public class DelegateQueryBuilder extends QueryBuilder
                 return invoke(delegate, context);
             }
         }
+        catch (PersistenceException e)
+        {
+            throw e;
+        }
         catch (Exception e)
         {
             throw new QueryInvocationException(e, context);
@@ -108,7 +113,11 @@ public class DelegateQueryBuilder extends QueryBuilder
         }
         catch (InvocationTargetException e)
         {
-            throw new RuntimeException(e);
+            if (e.getCause() != null && e.getCause() instanceof PersistenceException)
+            {
+                throw (PersistenceException) e.getCause();
+            }
+            throw new QueryInvocationException(e, context);
         }
         catch (IllegalAccessException e)
         {

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4e8d5831/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 4549cb6..8900d68 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
@@ -105,11 +105,18 @@ public class CdiQueryInvocationContext implements QueryInvocationContext
         return entityClass;
     }
 
+    @Override
+    public Class<?> getRepositoryClass()
+    {
+        return repoMethod.getRepository().getRepositoryClass();
+    }
+
     public Object proceed() throws Exception
     {
         return method.invoke(proxy, args);
     }
 
+    @Override
     public Method getMethod()
     {
         return method;

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4e8d5831/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryInvocationException.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryInvocationException.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryInvocationException.java
deleted file mode 100644
index 2b8c216..0000000
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryInvocationException.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.handler;
-
-import java.lang.reflect.Method;
-
-public class QueryInvocationException extends RuntimeException
-{
-
-    private static final long serialVersionUID = 1L;
-
-    public QueryInvocationException(Throwable t, CdiQueryInvocationContext context)
-    {
-        super(createMessage(context, t), t);
-    }
-
-    public QueryInvocationException(String message, CdiQueryInvocationContext context)
-    {
-        super(createMessage(context));
-    }
-
-    public QueryInvocationException(Throwable t, Class<?> proxy, Method method)
-    {
-        super(createMessage(proxy, method, t), t);
-    }
-
-    private static String createMessage(CdiQueryInvocationContext context)
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append("Failed calling Repository: [");
-        builder.append("Repository=").append(context.getRepositoryMethod()
-                .getRepository().getRepositoryClass().getName()).append(",");
-        builder.append("entity=").append(context.getEntityClass().getName()).append(",");
-        builder.append("method=").append(context.getMethod().getName()).append(",");
-        builder.append("query=").append(context.getQueryString()).append("],");
-        return builder.toString();
-    }
-
-    private static String createMessage(CdiQueryInvocationContext context, Throwable t)
-    {
-        StringBuilder builder = new StringBuilder(createMessage(context));
-        builder.append("exception=").append(t.getClass()).append(",message=").append(t.getMessage());
-        return builder.toString();
-    }
-
-    private static String createMessage(Class<?> proxy, Method method, Throwable t)
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append("Exception calling Repository: [");
-        builder.append("Repository=").append(proxy).append(",");
-        builder.append("method=").append(method.getName()).append("],");
-        builder.append("exception=").append(t.getClass()).append(",message=").append(t.getMessage());
-        return builder.toString();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4e8d5831/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/EntityManagerTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/EntityManagerTest.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/EntityManagerTest.java
index 18f2399..b49ae13 100644
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/EntityManagerTest.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/EntityManagerTest.java
@@ -26,6 +26,7 @@ import java.util.List;
 
 import javax.inject.Inject;
 
+import org.apache.deltaspike.data.api.QueryInvocationException;
 import org.apache.deltaspike.data.test.domain.Simple;
 import org.apache.deltaspike.data.test.service.SimpleRepositoryWithEntityManager;
 import org.apache.deltaspike.data.test.service.SimpleRepositoryWithEntityManagerResolver;

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4e8d5831/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 712eeb5..4904fda 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
@@ -29,6 +29,7 @@ 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;
@@ -309,7 +310,7 @@ public class QueryHandlerTest extends TransactionalTestCase
         assertNull(result2);
     }
 
-    @Test(expected = QueryInvocationException.class)
+    @Test(expected = NonUniqueResultException.class)
     public void should_fail_optinal_query_by_name_with_nonunique()
     {
         // given
@@ -321,7 +322,7 @@ public class QueryHandlerTest extends TransactionalTestCase
         repo.findOptionalByName(name);
     }
 
-    @Test(expected = QueryInvocationException.class)
+    @Test(expected = NonUniqueResultException.class)
     public void should_fail_optinal_query_by_annotation_with_nonunique()
     {
         // given

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4e8d5831/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
index f5ada14..64042f4 100755
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
@@ -26,6 +26,7 @@ import org.apache.deltaspike.data.api.FirstResult;
 import org.apache.deltaspike.data.api.MaxResults;
 import org.apache.deltaspike.data.api.Modifying;
 import org.apache.deltaspike.data.api.Query;
+import org.apache.deltaspike.data.api.QueryInvocationException;
 import org.apache.deltaspike.data.api.QueryParam;
 import org.apache.deltaspike.data.api.QueryResult;
 import org.apache.deltaspike.data.api.Repository;
@@ -122,7 +123,8 @@ public abstract class TestDeployments
                 .addClasses(AbstractEntityRepository.class, Repository.class, EntityRepository.class,
                         FirstResult.class, MaxResults.class, Modifying.class,
                         Query.class, QueryParam.class, QueryResult.class,
-                        EntityManagerConfig.class, EntityManagerResolver.class, SingleResultType.class)
+                        EntityManagerConfig.class, EntityManagerResolver.class, SingleResultType.class,
+                        QueryInvocationException.class)
                 .addClasses(Criteria.class, QuerySelection.class, CriteriaSupport.class)
                 .addClasses(CreatedOn.class, CurrentUser.class, ModifiedBy.class, ModifiedOn.class)
                 .addClasses(MappingConfig.class, QueryInOutMapper.class)


[3/3] git commit: DELTASPIKE-421 Documentation of optional query results

Posted by th...@apache.org.
DELTASPIKE-421 Documentation of optional query results


Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/c3f89b2f
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/c3f89b2f
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/c3f89b2f

Branch: refs/heads/master
Commit: c3f89b2fc2bf64bf0557bdd5a25404cee1ef166d
Parents: 4e8d583
Author: Thomas Hug <Th...@ctp-consulting.com>
Authored: Thu Nov 28 15:31:39 2013 +0100
Committer: Thomas Hug <Th...@ctp-consulting.com>
Committed: Thu Nov 28 15:31:39 2013 +0100

----------------------------------------------------------------------
 deltaspike/modules/data/README.adoc | 71 ++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/c3f89b2f/deltaspike/modules/data/README.adoc
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/README.adoc b/deltaspike/modules/data/README.adoc
index cbd887a..a48560c 100644
--- a/deltaspike/modules/data/README.adoc
+++ b/deltaspike/modules/data/README.adoc
@@ -627,6 +627,56 @@ public interface PersonRepository extends EntityRepository<Person, Long>
 Bulk operation query methods can either return void or int, which counts the number of entities affected
 by the bulk operation. 
 
+=== Optional Query Results
+
+The JPA spec requires to throw exceptions in case the +getSingleResult()+ method does either return no or more than one result. This can result in tedious handling with try-catch blocks or have potential impact on your transaction (as the +RuntimeException+ might roll it back).
+
+DeltaSpike Data gives the option to change this to the way it makes most sense for the current usecase. While the default behavior is still fully aligned with JPA, it's also possible to request optional query results.
+
+==== Zero or One Result
+
+With this option, the query returns +null+ instead of throwing a +NoResultException+ when there is no result returned. It's usable with method expressions, +Query+ annotations and +QueryResult<E>+ calls.
+
+[source,java]
+----
+@Repository(forEntity = Person.class)
+public interface PersonRepository
+{
+
+    Person findOptionalBySsn(String ssn);
+
+    @Query(named = Person.BY_NAME, singleResult = SingleResultType.OPTIONAL)
+    Person findByName(String firstName, String lastName);
+
+}
+----
+
+For method expressions, the +findOptionalBy+ prefix can be used. For +@Query+ annotations, the +singleResult+ attribute can be overridden with the +SingleResultType.OPTIONAL+ enum.
+
+In case the query returns more than one result, a +NonUniqueResultException+ is still thrown.
+
+==== Any Result
+
+If the caller does not really mind what kind if result is returned, it's also possible to request any result from the query. If there is no result, same as for optional queries +null+ is returned. In case there is more than one result, any result is returned, or more concretely the first result out of the result list.
+
+[source,java]
+----
+@Repository(forEntity = Person.class)
+public interface PersonRepository
+{
+
+    Person findAnyByLastName(String lastName);
+
+    @Query(named = Person.BY_NAME, singleResult = SingleResultType.ANY)
+    Person findByName(String firstName, String lastName);
+
+}
+----
+
+For method expressions, the +findAnyBy+ prefix can be used. For +@Query+ annotations, the +singleResult+ attribute can be overridden with the +SingleResultType.ANY+ enum.
+
+This option will not throw an exception.
+
 === Extensions
 
 ==== Query Delegates
@@ -777,6 +827,27 @@ In this case, the +forEntity+ attribute in the +@Repository+ annotation is manda
 to the mapper to convert parameters correctly (in this example, a conversion from a +PersonDto+
 parameter to +Person+ entity and from +PersonId+ to +Long+ is necessary).
 
+==== Simple Mappings
+
+In many cases it's just required to map a DTO object back and forth. For this case, the +SimpleQueryInOutMapperBase+ class can be subclassed, which only requires to override two methods:
+
+[source,java]
+----
+public class PersonMapper extends SimpleQueryInOutMapperBase<Person, PersonDto>
+{
+    @Override
+    protected PersonDto toDto(Person entity)
+    {
+        ...
+    }
+
+    @Override
+    protected Person toEntity(PersonDto dto) {
+        ...
+    }
+}
+----
+
 === JPA Criteria API Support
 
 Beside automatic query generation, the DeltaSpike data module also provides a DSL-like API to create JPA 2 Criteria queries.


[2/3] git commit: DELTASPIKE-421 Optional single results.

Posted by th...@apache.org.
DELTASPIKE-421 Optional single results.


Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/f3c00d8c
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/f3c00d8c
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/f3c00d8c

Branch: refs/heads/master
Commit: f3c00d8c722e357faba4b0527499d9daa5216453
Parents: feba6a7
Author: Thomas Hug <Th...@ctp-consulting.com>
Authored: Fri Nov 22 14:01:37 2013 +0100
Committer: Thomas Hug <Th...@ctp-consulting.com>
Committed: Thu Nov 28 14:38:25 2013 +0100

----------------------------------------------------------------------
 .../org/apache/deltaspike/data/api/Query.java   |   6 +
 .../apache/deltaspike/data/api/QueryResult.java |  15 ++
 .../apache/deltaspike/data/api/Repository.java  |   2 +-
 .../deltaspike/data/api/SingleResultType.java   |  46 ++++++
 .../deltaspike/data/api/criteria/Criteria.java  |  14 ++
 .../data/impl/builder/part/QueryRoot.java       |  21 ++-
 .../impl/builder/result/DefaultQueryResult.java |  21 +++
 .../impl/builder/result/QueryProcessor.java     |   4 +-
 .../builder/result/QueryProcessorFactory.java   |  30 +++-
 .../data/impl/criteria/QueryCriteria.java       |  21 +++
 .../impl/handler/CdiQueryInvocationContext.java |   8 +-
 .../data/impl/handler/QueryHandler.java         |   8 +-
 .../deltaspike/data/impl/meta/MethodPrefix.java | 145 +++++++++++++++++++
 .../data/impl/meta/RepositoryComponent.java     |  10 +-
 .../data/impl/meta/RepositoryMethod.java        |  16 +-
 .../deltaspike/data/impl/QueryResultTest.java   |  49 +++++++
 .../data/impl/builder/part/QueryRootTest.java   |  20 ++-
 .../data/impl/criteria/CriteriaTest.java        |  50 +++++++
 .../data/impl/handler/QueryHandlerTest.java     |  95 ++++++++++++
 .../test/service/SimpleCriteriaRepository.java  |  14 ++
 .../data/test/service/SimpleRepository.java     |  17 ++-
 .../data/test/util/TestDeployments.java         |   3 +-
 22 files changed, 577 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Query.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Query.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Query.java
index 23970ce..e03410c 100755
--- a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Query.java
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Query.java
@@ -72,4 +72,10 @@ public @interface Query
     QueryHint[] hints() default {
     };
 
+    /**
+     * Defines how a single result query is fetched. Defaults to the JPA way with
+     * Exceptions thrown on non-single result queries.
+     */
+    SingleResultType singleResult() default SingleResultType.JPA;
+
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryResult.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryResult.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryResult.java
index f3289a9..fce1a87 100644
--- a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryResult.java
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/QueryResult.java
@@ -149,6 +149,21 @@ public interface QueryResult<E>
     E getSingleResult();
 
     /**
+     * Fetch a single result entity. Returns {@code null} if no result is found.
+     *
+     * @return                  Entity retrieved by the query, or {@code null} if no result.
+     */
+    E getOptionalResult();
+
+    /**
+     * Fetch a single result entity. Returns {@code null} if no result is found. If the
+     * query finds multiple results, it simply returns the first one found.
+     *
+     * @return                  First Entity retrieved by the query, or {@code null} if no result.
+     */
+    E getAnyResult();
+
+    /**
      * Count the result set.
      * @return                  Result count.
      */

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Repository.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Repository.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Repository.java
index 0f86131..f1a1308 100755
--- a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Repository.java
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/Repository.java
@@ -47,6 +47,6 @@ public @interface Repository
      * The method prefix for method expressions. Can be adapted to
      * domain specific conventions.
      */
-    String methodPrefix() default "findBy";
+    String methodPrefix() default "";
 
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/SingleResultType.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/SingleResultType.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/SingleResultType.java
new file mode 100644
index 0000000..c2a54e8
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/SingleResultType.java
@@ -0,0 +1,46 @@
+/*
+ * 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.api;
+
+/**
+ * Defines the way a single result query is fetched.
+ */
+public enum SingleResultType
+{
+
+    /**
+     * Expects a single result, throws a {@link javax.persistence.NoResultException} or
+     * {@link javax.persistence.NonUniqueResultException} otherwise. This is the JPA
+     * default behavior.
+     */
+    JPA,
+
+    /**
+     * Expects a single result. Other than {@link SingleResultStyle#SINGLE} it returns {@code null}
+     * if no result is found.
+     */
+    OPTIONAL,
+
+    /**
+     * Returns any result, or {@code null} if nothing is found. If more than one result is found,
+     * it returns the first one from the result list.
+     */
+    ANY
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/Criteria.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/Criteria.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/Criteria.java
index 909034b..6dfedd1 100644
--- a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/Criteria.java
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/Criteria.java
@@ -55,6 +55,20 @@ public interface Criteria<C, R>
     R getSingleResult();
 
     /**
+     * Executes the query which has a single result. Returns {@code null}
+     * if there is no result.
+     * @return Entity matching the search query, or {@code null} if there is none.
+     */
+    R getOptionalResult();
+
+    /**
+     * Executes the query and returns a single result. If there are
+     * multiple results, the first received is returned.
+     * @return Entity matching the search query.
+     */
+    R getAnyResult();
+
+    /**
      * Creates a JPA query object to be executed.
      * @return A {@link TypedQuery} object ready to return results.
      */

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryRoot.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryRoot.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryRoot.java
index 1774125..9484634 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryRoot.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryRoot.java
@@ -28,6 +28,7 @@ import java.util.logging.Logger;
 import org.apache.deltaspike.data.impl.builder.MethodExpressionException;
 import org.apache.deltaspike.data.impl.builder.QueryBuilder;
 import org.apache.deltaspike.data.impl.builder.QueryBuilderContext;
+import org.apache.deltaspike.data.impl.meta.MethodPrefix;
 import org.apache.deltaspike.data.impl.meta.RepositoryComponent;
 
 /**
@@ -36,24 +37,24 @@ import org.apache.deltaspike.data.impl.meta.RepositoryComponent;
 public class QueryRoot extends QueryPart
 {
 
-    public static final QueryRoot UNKNOWN_ROOT = new QueryRoot("null-object", "");
+    public static final QueryRoot UNKNOWN_ROOT = new QueryRoot("null-object", new MethodPrefix("", null));
 
     private static final Logger log = Logger.getLogger(QueryRoot.class.getName());
 
     private final String entityName;
-    private final String queryPrefix;
+    private final MethodPrefix methodPrefix;
 
     private String jpqlQuery;
 
-    protected QueryRoot(String entityName, String queryPrefix)
+    protected QueryRoot(String entityName, MethodPrefix methodPrefix)
     {
         this.entityName = entityName;
-        this.queryPrefix = queryPrefix;
+        this.methodPrefix = methodPrefix;
     }
 
-    public static QueryRoot create(String method, RepositoryComponent repo)
+    public static QueryRoot create(String method, RepositoryComponent repo, MethodPrefix prefix)
     {
-        QueryRoot root = new QueryRoot(repo.getEntityName(), repo.getMethodPrefix());
+        QueryRoot root = new QueryRoot(repo.getEntityName(), prefix);
         root.build(method, method, repo);
         root.createJpql();
         return root;
@@ -121,16 +122,12 @@ public class QueryRoot extends QueryPart
 
     private boolean hasQueryConditions(String[] orderByParts)
     {
-        return !queryPrefix.equals(orderByParts[0]);
+        return !methodPrefix.getPrefix().equals(orderByParts[0]);
     }
 
     private String removePrefix(String queryPart)
     {
-        if (queryPart.startsWith(queryPrefix))
-        {
-            return queryPart.substring(queryPrefix.length());
-        }
-        return queryPart;
+        return methodPrefix.removePrefix(queryPart);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/DefaultQueryResult.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/DefaultQueryResult.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/DefaultQueryResult.java
index a0fafb3..557d156 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/DefaultQueryResult.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/DefaultQueryResult.java
@@ -23,6 +23,7 @@ import java.util.List;
 
 import javax.persistence.FlushModeType;
 import javax.persistence.LockModeType;
+import javax.persistence.NoResultException;
 import javax.persistence.Query;
 import javax.persistence.metamodel.SingularAttribute;
 
@@ -186,6 +187,26 @@ public class DefaultQueryResult<T> implements QueryResult<T>
     }
 
     @Override
+    public T getOptionalResult()
+    {
+        try
+        {
+            return getSingleResult();
+        }
+        catch (NoResultException e)
+        {
+            return null;
+        }
+    }
+
+    @Override
+    public T getAnyResult()
+    {
+        List<T> queryResult = getResultList();
+        return queryResult.size() > 0 ? queryResult.get(0) : null;
+    }
+
+    @Override
     public long count()
     {
         CountQueryPostProcessor counter = new CountQueryPostProcessor();

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessor.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessor.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessor.java
index b39b9ee..deb7993 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessor.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessor.java
@@ -20,9 +20,11 @@ package org.apache.deltaspike.data.impl.builder.result;
 
 import javax.persistence.Query;
 
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+
 public interface QueryProcessor
 {
 
-    Object executeQuery(Query query);
+    Object executeQuery(Query query, CdiQueryInvocationContext context);
 
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java
index 4b14616..022c22a 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java
@@ -21,10 +21,13 @@ package org.apache.deltaspike.data.impl.builder.result;
 import java.lang.reflect.Method;
 import java.util.List;
 
+import javax.persistence.NoResultException;
 import javax.persistence.Query;
 
 import org.apache.deltaspike.data.api.Modifying;
 import org.apache.deltaspike.data.api.QueryResult;
+import org.apache.deltaspike.data.api.SingleResultType;
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
 
 public final class QueryProcessorFactory
 {
@@ -74,7 +77,7 @@ public final class QueryProcessorFactory
     private static final class ListQueryProcessor implements QueryProcessor
     {
         @Override
-        public Object executeQuery(Query query)
+        public Object executeQuery(Query query, CdiQueryInvocationContext context)
         {
             return query.getResultList();
         }
@@ -83,7 +86,7 @@ public final class QueryProcessorFactory
     private static final class NoOpQueryProcessor implements QueryProcessor
     {
         @Override
-        public Object executeQuery(Query query)
+        public Object executeQuery(Query query, CdiQueryInvocationContext context)
         {
             return query;
         }
@@ -92,9 +95,26 @@ public final class QueryProcessorFactory
     private static final class SingleResultQueryProcessor implements QueryProcessor
     {
         @Override
-        public Object executeQuery(Query query)
+        public Object executeQuery(Query query, CdiQueryInvocationContext context)
         {
-            return query.getSingleResult();
+            SingleResultType style = context.getSingleResultStyle();
+            switch (style)
+            {
+                case JPA:
+                    return query.getSingleResult();
+                case OPTIONAL:
+                    try
+                    {
+                        return query.getSingleResult();
+                    }
+                    catch (NoResultException e)
+                    {
+                        return null;
+                    }
+                default:
+                    List<Object> queryResult = query.getResultList();
+                    return queryResult.size() > 0 ? queryResult.get(0) : null;
+            }
         }
     }
 
@@ -109,7 +129,7 @@ public final class QueryProcessorFactory
         }
 
         @Override
-        public Object executeQuery(Query query)
+        public Object executeQuery(Query query, CdiQueryInvocationContext context)
         {
             int result = query.executeUpdate();
             if (!returnsVoid)

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/QueryCriteria.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/QueryCriteria.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/QueryCriteria.java
index 63438db..0c054e3 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/QueryCriteria.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/QueryCriteria.java
@@ -27,6 +27,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
 import javax.persistence.TypedQuery;
 import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
@@ -112,6 +113,26 @@ public class QueryCriteria<C, R> implements Criteria<C, R>
     }
 
     @Override
+    public R getOptionalResult()
+    {
+        try
+        {
+            return getSingleResult();
+        }
+        catch (NoResultException e)
+        {
+            return null;
+        }
+    }
+
+    @Override
+    public R getAnyResult()
+    {
+        List<R> queryResult = getResultList();
+        return queryResult.size() > 0 ? queryResult.get(0) : null;
+    }
+
+    @Override
     public TypedQuery<R> createQuery()
     {
         try

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/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 c4dd208..4549cb6 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
@@ -25,6 +25,7 @@ import java.util.List;
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
 
+import org.apache.deltaspike.data.api.SingleResultType;
 import org.apache.deltaspike.data.api.mapping.QueryInOutMapper;
 import org.apache.deltaspike.data.impl.meta.RepositoryMethod;
 import org.apache.deltaspike.data.impl.param.Parameters;
@@ -175,7 +176,7 @@ public class CdiQueryInvocationContext implements QueryInvocationContext
 
     public Object executeQuery(Query jpaQuery)
     {
-        return repoMethod.getQueryProcessor().executeQuery(jpaQuery);
+        return repoMethod.getQueryProcessor().executeQuery(jpaQuery, this);
     }
 
     public Parameters getParams()
@@ -213,4 +214,9 @@ public class CdiQueryInvocationContext implements QueryInvocationContext
         return repoMethod.getQueryInOutMapperInstance(this);
     }
 
+    public SingleResultType getSingleResultStyle()
+    {
+        return repoMethod.getSingleResultStyle();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java
index 809a9a8..f743cb8 100755
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java
@@ -29,7 +29,9 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.inject.Inject;
+import javax.persistence.PersistenceException;
 
+import org.apache.deltaspike.data.api.QueryInvocationException;
 import org.apache.deltaspike.data.api.Repository;
 import org.apache.deltaspike.data.impl.builder.QueryBuilder;
 import org.apache.deltaspike.data.impl.builder.QueryBuilderFactory;
@@ -76,9 +78,13 @@ public class QueryHandler implements Serializable, InvocationHandler
             Object result = builder.executeQuery(queryContext);
             return result;
         }
+        catch (PersistenceException e)
+        {
+            throw e;
+        }
         catch (Exception e)
         {
-            log.log(Level.SEVERE, "Query execution error", e);
+            log.log(Level.FINEST, "Query execution error", e);
             if (queryContext != null)
             {
                 throw new QueryInvocationException(e, queryContext);

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/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
new file mode 100644
index 0000000..81d8ea2
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/MethodPrefix.java
@@ -0,0 +1,145 @@
+/*
+ * 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.apache.deltaspike.data.api.SingleResultType;
+
+public class MethodPrefix
+{
+    public static final String DEFAULT_PREFIX = "findBy";
+    public static final String DEFAULT_OPT_PREFIX = "findOptionalBy";
+    public static final String DEFAULT_ANY_PREFIX = "findAnyBy";
+
+    private final String customPrefix;
+    private final String methodName;
+
+    public MethodPrefix(String customPrefix, String methodName)
+    {
+        this.customPrefix = customPrefix;
+        this.methodName = methodName;
+    }
+
+    public String removePrefix(String queryPart)
+    {
+        if (hasCustomPrefix() && queryPart.startsWith(customPrefix))
+        {
+            return queryPart.substring(customPrefix.length());
+        }
+        KnownQueryPrefix known = KnownQueryPrefix.fromMethodName(queryPart);
+        if (known != null)
+        {
+            return known.removePrefix(queryPart);
+        }
+        return queryPart;
+    }
+
+    public boolean hasCustomPrefix()
+    {
+        return !"".equals(customPrefix);
+    }
+
+    public String getCustomPrefix()
+    {
+        return customPrefix;
+    }
+
+    public String getPrefix()
+    {
+        if (hasCustomPrefix())
+        {
+            return customPrefix;
+        }
+        KnownQueryPrefix prefix = KnownQueryPrefix.fromMethodName(methodName);
+        if (prefix != null)
+        {
+            return prefix.getPrefix();
+        }
+        return "";
+    }
+
+    public SingleResultType getSingleResultStyle()
+    {
+        KnownQueryPrefix prefix = KnownQueryPrefix.fromMethodName(methodName);
+        if (prefix != null)
+        {
+            return prefix.getStyle();
+        }
+        return SingleResultType.JPA;
+    }
+
+    private static enum KnownQueryPrefix
+    {
+        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)
+        {
+            @Override
+            public SingleResultType getStyle()
+            {
+                return SingleResultType.ANY;
+            }
+        };
+
+        private final String prefix;
+
+        private KnownQueryPrefix(String prefix)
+        {
+            this.prefix = prefix;
+        }
+
+        public String removePrefix(String queryPart)
+        {
+            return queryPart.substring(prefix.length());
+        }
+
+        public String getPrefix()
+        {
+            return prefix;
+        }
+
+        public abstract SingleResultType getStyle();
+
+        public static KnownQueryPrefix fromMethodName(String name)
+        {
+            for (KnownQueryPrefix mapping : values())
+            {
+                if (name.startsWith(mapping.getPrefix()))
+                {
+                    return mapping;
+                }
+            }
+            return null;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponent.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponent.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponent.java
index 2943555..25f9cc4 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponent.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponent.java
@@ -169,11 +169,6 @@ public class RepositoryComponent
         return repoClass;
     }
 
-    public String getMethodPrefix()
-    {
-        return repoClass.getAnnotation(Repository.class).methodPrefix();
-    }
-
     public boolean hasEntityManagerResolver()
     {
         return getEntityManagerResolverClass() != null;
@@ -255,4 +250,9 @@ public class RepositoryComponent
         return null;
     }
 
+    public String getCustomMethodPrefix()
+    {
+        return repoClass.getAnnotation(Repository.class).methodPrefix();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/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 ec79d3f..ac90562 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
@@ -32,6 +32,7 @@ import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
 import org.apache.deltaspike.core.api.provider.BeanProvider;
 import org.apache.deltaspike.core.api.provider.DependentProvider;
 import org.apache.deltaspike.data.api.Query;
+import org.apache.deltaspike.data.api.SingleResultType;
 import org.apache.deltaspike.data.api.mapping.MappingConfig;
 import org.apache.deltaspike.data.api.mapping.QueryInOutMapper;
 import org.apache.deltaspike.data.impl.builder.MethodExpressionException;
@@ -55,6 +56,7 @@ public class RepositoryMethod
 
     private final Method method;
     private final MethodType methodType;
+    private final MethodPrefix methodPrefix;
     private final RepositoryComponent repo;
     private final QueryRoot queryRoot;
     private final QueryProcessor queryProcessor;
@@ -66,6 +68,7 @@ public class RepositoryMethod
     {
         this.method = method;
         this.repo = repo;
+        this.methodPrefix = new MethodPrefix(repo.getCustomMethodPrefix(), method.getName());
         this.methodType = extractMethodType();
         this.queryRoot = initQueryRoot();
         this.queryProcessor = QueryProcessorFactory.newInstance(method).build();
@@ -115,7 +118,7 @@ public class RepositoryMethod
     {
         if (methodType == MethodType.PARSE)
         {
-            return QueryRoot.create(method.getName(), repo);
+            return QueryRoot.create(method.getName(), repo, methodPrefix);
         }
         return QueryRoot.UNKNOWN_ROOT;
     }
@@ -143,7 +146,7 @@ public class RepositoryMethod
         }
         try
         {
-            QueryRoot.create(method.getName(), repo);
+            QueryRoot.create(method.getName(), repo, methodPrefix);
             return true;
         }
         catch (MethodExpressionException e)
@@ -218,4 +221,13 @@ public class RepositoryMethod
         return mapper != null;
     }
 
+    public SingleResultType getSingleResultStyle()
+    {
+        if (method.isAnnotationPresent(Query.class))
+        {
+            return method.getAnnotation(Query.class).singleResult();
+        }
+        return methodPrefix.getSingleResultStyle();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/QueryResultTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/QueryResultTest.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/QueryResultTest.java
index 90bcc9a..55db66f 100644
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/QueryResultTest.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/QueryResultTest.java
@@ -21,6 +21,7 @@ package org.apache.deltaspike.data.impl;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -31,6 +32,7 @@ import javax.inject.Inject;
 import javax.persistence.EntityManager;
 import javax.persistence.FlushModeType;
 import javax.persistence.LockModeType;
+import javax.persistence.NonUniqueResultException;
 import javax.persistence.PersistenceContext;
 
 import org.apache.deltaspike.data.api.QueryResult;
@@ -280,6 +282,53 @@ public class QueryResultTest extends TransactionalTestCase
         assertEquals(2L, result);
     }
 
+    @Test
+    public void should_query_optional()
+    {
+        // given
+        final String name = "should_query_optional";
+        builder.createSimple(name);
+
+        // when
+        Simple result1 = repo.queryResultWithNamed(name).getOptionalResult();
+        Simple result2 = repo.queryResultWithNamed("this_does_not_exist").getOptionalResult();
+
+        // then
+        assertNotNull(result1);
+        assertEquals(name, result1.getName());
+        assertNull(result2);
+    }
+
+    @Test(expected = NonUniqueResultException.class)
+    public void should_fail_query_optional_with_nonunique()
+    {
+        // given
+        final String name = "should_fail_query_optional_with_nonunique";
+        builder.createSimple(name);
+        builder.createSimple(name);
+
+        // when
+        repo.queryResultWithNamed(name).getOptionalResult();
+    }
+
+    @Test
+    public void should_query_any()
+    {
+        // given
+        final String name = "should_query_any";
+        builder.createSimple(name);
+        builder.createSimple(name);
+
+        // when
+        Simple result1 = repo.queryResultWithNamed(name).getAnyResult();
+        Simple result2 = repo.queryResultWithNamed("this_does_not_exist").getAnyResult();
+
+        // then
+        assertNotNull(result1);
+        assertEquals(name, result1.getName());
+        assertNull(result2);
+    }
+
     @Before
     public void setup()
     {

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/builder/part/QueryRootTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/builder/part/QueryRootTest.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/builder/part/QueryRootTest.java
index 4279e62..3184669 100644
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/builder/part/QueryRootTest.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/builder/part/QueryRootTest.java
@@ -21,6 +21,7 @@ package org.apache.deltaspike.data.impl.builder.part;
 import static org.junit.Assert.assertEquals;
 
 import org.apache.deltaspike.data.impl.builder.MethodExpressionException;
+import org.apache.deltaspike.data.impl.meta.MethodPrefix;
 import org.apache.deltaspike.data.impl.meta.RepositoryComponent;
 import org.apache.deltaspike.data.impl.meta.RepositoryEntity;
 import org.apache.deltaspike.data.test.domain.Simple;
@@ -43,7 +44,7 @@ public class QueryRootTest
                         "where e.name = ?1";
 
         // when
-        String result = QueryRoot.create(name, repo).getJpqlQuery().trim();
+        String result = QueryRoot.create(name, repo, prefix(name)).getJpqlQuery().trim();
 
         // then
         assertEquals(expected, result);
@@ -65,7 +66,7 @@ public class QueryRootTest
                         "order by e.embedded.embedd desc";
 
         // when
-        String result = QueryRoot.create(name, repo).getJpqlQuery().trim();
+        String result = QueryRoot.create(name, repo, prefix(name)).getJpqlQuery().trim();
 
         // then
         assertEquals(expected, result);
@@ -81,7 +82,7 @@ public class QueryRootTest
                         "order by e.id asc";
 
         // when
-        String result = QueryRoot.create(name, repo).getJpqlQuery().trim();
+        String result = QueryRoot.create(name, repo, prefix(name)).getJpqlQuery().trim();
 
         // then
         assertEquals(expected, result);
@@ -94,7 +95,7 @@ public class QueryRootTest
         final String name = "findByInvalid";
 
         // when
-        QueryRoot.create(name, repo);
+        QueryRoot.create(name, repo, prefix(name));
     }
 
     @Test(expected = MethodExpressionException.class)
@@ -104,7 +105,7 @@ public class QueryRootTest
         final String name = "findBy";
 
         // when
-        QueryRoot.create(name, repo);
+        QueryRoot.create(name, repo, prefix(name));
     }
 
     @Test(expected = MethodExpressionException.class)
@@ -114,7 +115,7 @@ public class QueryRootTest
         final String name = "findByNameOrderByInvalidDesc";
 
         // when
-        QueryRoot.create(name, repo);
+        QueryRoot.create(name, repo, prefix(name));
     }
 
     @Test
@@ -127,10 +128,15 @@ public class QueryRootTest
                         "where e.name = ?1";
 
         // when
-        String result = QueryRoot.create(name, repoFetchBy).getJpqlQuery().trim();
+        String result = QueryRoot.create(name, repoFetchBy, new MethodPrefix("fetchBy", name)).getJpqlQuery().trim();
 
         // then
         assertEquals(expected, result);
     }
 
+    private MethodPrefix prefix(final String name)
+    {
+        return new MethodPrefix("", name);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/criteria/CriteriaTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/criteria/CriteriaTest.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/criteria/CriteriaTest.java
index 8368c7b..06a4d2d 100644
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/criteria/CriteriaTest.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/criteria/CriteriaTest.java
@@ -20,8 +20,10 @@ package org.apache.deltaspike.data.impl.criteria;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.lang.reflect.InvocationTargetException;
 import java.util.List;
 
 import javax.enterprise.inject.Produces;
@@ -289,6 +291,54 @@ public class CriteriaTest extends TransactionalTestCase
         }
     }
 
+    @Test
+    public void should_create_select_criteria_with_optional_result()
+    {
+        // given
+        final String name = "should_create_select_criteria_with_optional_result";
+        createSimple(name, 10);
+
+        // when
+        Simple result1 = repo.queryOptional(name);
+        Simple result2 = repo.queryOptional(name + "_doesnt exist");
+
+        // then
+        assertNotNull(result1);
+        assertEquals(name, result1.getName());
+        assertNull(result2);
+    }
+
+    @Test(expected = InvocationTargetException.class)
+    public void should_fail_with_optional_nonunique_result()
+    {
+        // given
+        final String name = "should_fail_with_optional_nonunique_result";
+        createSimple(name, 10);
+        createSimple(name, 10);
+
+        // when
+        repo.queryOptional(name);
+
+    }
+
+    @Test
+    public void should_create_select_criteria_with_any_result()
+    {
+        // given
+        final String name = "should_create_select_criteria_with_any_result";
+        createSimple(name, 10);
+        createSimple(name, 10);
+
+        // when
+        Simple result1 = repo.queryAny(name);
+        Simple result2 = repo.queryAny(name + "_doesnt exist");
+
+        // then
+        assertNotNull(result1);
+        assertEquals(name, result1.getName());
+        assertNull(result2);
+    }
+
     @Override
     protected EntityManager getEntityManager()
     {

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/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 b1076d0..712eeb5 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
@@ -21,6 +21,7 @@ package org.apache.deltaspike.data.impl.handler;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.util.List;
@@ -274,6 +275,100 @@ public class QueryHandlerTest extends TransactionalTestCase
         assertEquals(1, count);
     }
 
+    @Test
+    public void should_create_optinal_query_by_name()
+    {
+        // given
+        final String name = "should_create_optinal_query_by_name";
+        builder.createSimple(name);
+
+        // when
+        Simple result1 = repo.findOptionalByName(name);
+        Simple result2 = repo.findOptionalByName(name + "_doesnt_exist");
+
+        // then
+        assertNotNull(result1);
+        assertEquals(name, result1.getName());
+        assertNull(result2);
+    }
+
+    @Test
+    public void should_create_optinal_query_by_annotation()
+    {
+        // given
+        final String name = "should_create_optinal_query_by_annotation";
+        builder.createSimple(name);
+
+        // when
+        Simple result1 = repo.findByNameOptional(name);
+        Simple result2 = repo.findByNameOptional(name + "_doesnt_exist");
+
+        // then
+        assertNotNull(result1);
+        assertEquals(name, result1.getName());
+        assertNull(result2);
+    }
+
+    @Test(expected = QueryInvocationException.class)
+    public void should_fail_optinal_query_by_name_with_nonunique()
+    {
+        // given
+        final String name = "should_fail_optinal_query_by_name_with_nonunique";
+        builder.createSimple(name);
+        builder.createSimple(name);
+
+        // when
+        repo.findOptionalByName(name);
+    }
+
+    @Test(expected = QueryInvocationException.class)
+    public void should_fail_optinal_query_by_annotation_with_nonunique()
+    {
+        // given
+        final String name = "should_fail_optinal_query_by_annotation_with_nonunique";
+        builder.createSimple(name);
+        builder.createSimple(name);
+
+        // when
+        repo.findByNameOptional(name);
+    }
+
+    @Test
+    public void should_create_any_query_by_name()
+    {
+        // given
+        final String name = "should_create_any_query_by_name";
+        builder.createSimple(name);
+        builder.createSimple(name);
+
+        // when
+        Simple result1 = repo.findAnyByName(name);
+        Simple result2 = repo.findAnyByName(name + "_doesnt_exist");
+
+        // then
+        assertNotNull(result1);
+        assertEquals(name, result1.getName());
+        assertNull(result2);
+    }
+
+    @Test
+    public void should_create_any_query_by_annotation()
+    {
+        // given
+        final String name = "should_create_any_query_by_annotation";
+        builder.createSimple(name);
+        builder.createSimple(name);
+
+        // when
+        Simple result1 = repo.findByNameAny(name);
+        Simple result2 = repo.findByNameAny(name + "_doesnt_exist");
+
+        // then
+        assertNotNull(result1);
+        assertEquals(name, result1.getName());
+        assertNull(result2);
+    }
+
     @Before
     public void setup()
     {

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleCriteriaRepository.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleCriteriaRepository.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleCriteriaRepository.java
index 3c5a159..a4cca1c 100644
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleCriteriaRepository.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleCriteriaRepository.java
@@ -40,6 +40,20 @@ public abstract class SimpleCriteriaRepository extends AbstractEntityRepository<
                 .getResultList();
     }
 
+    public Simple queryOptional(String name)
+    {
+        return criteria()
+                .eq(Simple_.name, name)
+                .getOptionalResult();
+    }
+
+    public Simple queryAny(String name)
+    {
+        return criteria()
+                .eq(Simple_.name, name)
+                .getAnyResult();
+    }
+
     @SuppressWarnings("unchecked")
     public Statistics queryWithSelect(String name)
     {

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f3c00d8c/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 21c41cb..f3d1d07 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
@@ -18,10 +18,13 @@
  */
 package org.apache.deltaspike.data.test.service;
 
+import static javax.persistence.LockModeType.PESSIMISTIC_WRITE;
+import static org.apache.deltaspike.data.api.SingleResultType.ANY;
+import static org.apache.deltaspike.data.api.SingleResultType.OPTIONAL;
+
 import java.util.List;
 
 import javax.persistence.EntityManager;
-import javax.persistence.LockModeType;
 
 import org.apache.deltaspike.data.api.AbstractEntityRepository;
 import org.apache.deltaspike.data.api.FirstResult;
@@ -48,11 +51,17 @@ public abstract class SimpleRepository extends AbstractEntityRepository<Simple,
     @Query(named = Simple.BY_NAME_ENABLED, max = 1)
     public abstract List<Simple> findByNamedQueryIndexed(String name, Boolean enabled);
 
+    @Query(named = Simple.BY_NAME_LIKE, singleResult = OPTIONAL)
+    public abstract Simple findByNameOptional(String name);
+
+    @Query(named = Simple.BY_NAME_LIKE, singleResult = ANY)
+    public abstract Simple findByNameAny(String name);
+
     @Query(named = Simple.BY_NAME_ENABLED)
     public abstract List<Simple> findByNamedQueryRestricted(String name, Boolean enabled,
             @MaxResults int max, @FirstResult Integer first);
 
-    @Query(named = Simple.BY_ID, lock = LockModeType.PESSIMISTIC_WRITE)
+    @Query(named = Simple.BY_ID, lock = PESSIMISTIC_WRITE)
     public abstract Simple findByNamedQueryNamed(
             @QueryParam("id") Long id, @QueryParam("enabled") Boolean enabled);
 
@@ -64,6 +73,10 @@ public abstract class SimpleRepository extends AbstractEntityRepository<Simple,
 
     public abstract Simple findByNameAndEnabled(String name, Boolean enabled);
 
+    public abstract Simple findOptionalByName(String name);
+
+    public abstract Simple findAnyByName(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/f3c00d8c/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
index c93ce26..f5ada14 100755
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java
@@ -29,6 +29,7 @@ import org.apache.deltaspike.data.api.Query;
 import org.apache.deltaspike.data.api.QueryParam;
 import org.apache.deltaspike.data.api.QueryResult;
 import org.apache.deltaspike.data.api.Repository;
+import org.apache.deltaspike.data.api.SingleResultType;
 import org.apache.deltaspike.data.api.audit.CreatedOn;
 import org.apache.deltaspike.data.api.audit.CurrentUser;
 import org.apache.deltaspike.data.api.audit.ModifiedBy;
@@ -121,7 +122,7 @@ public abstract class TestDeployments
                 .addClasses(AbstractEntityRepository.class, Repository.class, EntityRepository.class,
                         FirstResult.class, MaxResults.class, Modifying.class,
                         Query.class, QueryParam.class, QueryResult.class,
-                        EntityManagerConfig.class, EntityManagerResolver.class)
+                        EntityManagerConfig.class, EntityManagerResolver.class, SingleResultType.class)
                 .addClasses(Criteria.class, QuerySelection.class, CriteriaSupport.class)
                 .addClasses(CreatedOn.class, CurrentUser.class, ModifiedBy.class, ModifiedOn.class)
                 .addClasses(MappingConfig.class, QueryInOutMapper.class)