diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaCountQueryCreator.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaCountQueryCreator.java index 4ec54023d..baf3a2a12 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaCountQueryCreator.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaCountQueryCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 the original author or authors. + * Copyright 2008-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,25 +40,16 @@ public class JpaCountQueryCreator extends JpaQueryCreator { */ public JpaCountQueryCreator(PartTree tree, Class domainClass, CriteriaBuilder builder, ParameterMetadataProvider provider) { - super(tree, domainClass, builder, provider); } /* * (non-Javadoc) - * - * @see - * org.springframework.data.jpa.repository.query.JpaQueryCreator#complete - * (javax.persistence.criteria.Predicate, - * org.springframework.data.domain.Sort, - * javax.persistence.criteria.CriteriaQuery, - * javax.persistence.criteria.CriteriaBuilder, - * javax.persistence.criteria.Root) + * @see org.springframework.data.jpa.repository.query.JpaQueryCreator#complete(javax.persistence.criteria.Predicate, org.springframework.data.domain.Sort, javax.persistence.criteria.CriteriaQuery, javax.persistence.criteria.CriteriaBuilder, javax.persistence.criteria.Root) */ @Override protected CriteriaQuery complete(Predicate predicate, Sort sort, CriteriaQuery query, CriteriaBuilder builder, Root root) { - return query.select(builder.count(root)).where(predicate); } } diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java index 9d892d9e6..ca13f298e 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 the original author or authors. + * Copyright 2008-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,8 @@ import javax.persistence.NoResultException; import javax.persistence.Query; import javax.persistence.TypedQuery; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.repository.query.ParameterAccessor; @@ -39,11 +41,13 @@ import org.springframework.util.Assert; */ public abstract class JpaQueryExecution { + private static final ConversionService conversionService = new DefaultConversionService(); + /** * Executes the given {@link AbstractStringBasedJpaQuery} with the given {@link ParameterBinder}. * - * @param query - * @param binder + * @param query must not be {@literal null}. + * @param binder must not be {@literal null}. * @return */ public Object execute(AbstractJpaQuery query, Object[] values) { @@ -51,11 +55,26 @@ public abstract class JpaQueryExecution { Assert.notNull(query); Assert.notNull(values); + Object result; + try { - return doExecute(query, values); + result = doExecute(query, values); } catch (NoResultException e) { return null; } + + if (result == null) { + return result; + } + + JpaQueryMethod queryMethod = query.getQueryMethod(); + Class requiredType = queryMethod.getReturnType(); + + if (void.class.equals(requiredType) || requiredType.isAssignableFrom(result.getClass())) { + return result; + } + + return conversionService.convert(result, requiredType); } /** diff --git a/src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java b/src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java index 868c06bfe..55e109748 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 the original author or authors. + * Copyright 2008-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,8 +46,8 @@ public class PartTreeJpaQuery extends AbstractJpaQuery { /** * Creates a new {@link PartTreeJpaQuery}. * - * @param method - * @param em + * @param method must not be {@literal null}. + * @param em must not be {@literal null}. */ public PartTreeJpaQuery(JpaQueryMethod method, EntityManager em) { @@ -57,8 +57,8 @@ public class PartTreeJpaQuery extends AbstractJpaQuery { this.tree = new PartTree(method.getName(), domainClass); this.parameters = method.getParameters(); - this.query = new QueryPreparer(parameters.potentiallySortsDynamically()); this.countQuery = new CountQueryPreparer(parameters.potentiallySortsDynamically()); + this.query = tree.isCountProjection() ? countQuery : new QueryPreparer(parameters.potentiallySortsDynamically()); } /* @@ -163,15 +163,12 @@ public class PartTreeJpaQuery extends AbstractJpaQuery { private class CountQueryPreparer extends QueryPreparer { public CountQueryPreparer(boolean recreateQueries) { - super(recreateQueries); } /* * (non-Javadoc) - * - * @see org.springframework.data.jpa.repository.query.PartTreeJpaQuery. - * QueryPreparer#createCreator() + * @see org.springframework.data.jpa.repository.query.PartTreeJpaQuery.QueryPreparer#createCreator(org.springframework.data.repository.query.ParametersParameterAccessor) */ @Override protected JpaQueryCreator createCreator(ParametersParameterAccessor accessor) { @@ -191,8 +188,8 @@ public class PartTreeJpaQuery extends AbstractJpaQuery { * @see org.springframework.data.jpa.repository.query.PartTreeJpaQuery.QueryPreparer#invokeBinding(org.springframework.data.jpa.repository.query.ParameterBinder, * javax.persistence.TypedQuery) */ + @Override protected Query invokeBinding(ParameterBinder binder, javax.persistence.TypedQuery query) { - return binder.bind(query); } } diff --git a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java index 251798086..c2c8cdd39 100644 --- a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java @@ -1027,6 +1027,28 @@ public class UserRepositoryTests { assertThat(result, hasItem(thirdUser)); } + /** + * @see DATAJPA-231 + */ + @Test + public void executesDerivedCountQueryToLong() { + + flushTestUsers(); + + assertThat(repository.countByLastname("Matthews"), is(1L)); + } + + /** + * @see DATAJPA-231 + */ + @Test + public void executesDerivedCountQueryToInt() { + + flushTestUsers(); + + assertThat(repository.countUsersByFirstname("Dave"), is(1)); + } + private Page executeSpecWithSort(Sort sort) { flushTestUsers(); diff --git a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryExecutionUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryExecutionUnitTests.java index e8f24ef97..c159da311 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryExecutionUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryExecutionUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 the original author or authors. + * Copyright 2008-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -88,6 +88,7 @@ public class JpaQueryExecutionUnitTests { when(query.executeUpdate()).thenReturn(0); when(method.getReturnType()).thenReturn((Class) void.class); when(jpaQuery.createQuery(Mockito.any(Object[].class))).thenReturn(query); + when(jpaQuery.getQueryMethod()).thenReturn(method); ModifyingExecution execution = new ModifyingExecution(method, em); execution.execute(jpaQuery, new Object[] {}); diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java b/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java index c9d699d89..acff3a0ef 100644 --- a/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java +++ b/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java @@ -254,4 +254,14 @@ public interface UserRepository extends JpaRepository, JpaSpecifi @Query(value = "SELECT 1 FROM User", nativeQuery = true) List findOnesByNativeQuery(); + + /** + * @see DATAJPA-231 + */ + long countByLastname(String lastname); + + /** + * @see DATAJPA-231 + */ + int countUsersByFirstname(String firstname); }