From 2db3b9b5dfa9ec394f7d327b88dc4d7a35926f82 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Mon, 7 Jul 2014 14:50:27 +0200 Subject: [PATCH] DATAJPA-506 - Re-enabled query method invocation with wrapper type results. The custom handling for Blobs applies to strict conversion as it uses the simple method return type to decide whether to trigger a conversion. It now rather uses the returned domain type which automatically unwraps wrapper types like Guava's Optional. Applied some polishing to the ConversionService setup in JpaQueryExecution to make more obvious that it's only mean to execute very specific conversions. Added Guava as test dependency and explicit dependency for the Mysema APT plugin as the test scope only would make it invisible for the plugin. --- pom.xml | 12 ++++++++++++ .../jpa/repository/query/JpaQueryExecution.java | 13 ++++++++++--- .../data/jpa/repository/UserRepositoryTests.java | 16 ++++++++++++++++ .../jpa/repository/sample/UserRepository.java | 12 ++++++++++-- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 715c4629e..48280678e 100644 --- a/pom.xml +++ b/pom.xml @@ -217,6 +217,13 @@ test + + com.google.guava + guava + 17.0 + test + + @@ -409,6 +416,11 @@ hibernate-jpamodelgen 1.3.0.Final + + com.google.guava + guava + 17.0 + 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 ace073b0e..37112a1ff 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 @@ -24,7 +24,9 @@ import javax.persistence.Query; import javax.persistence.StoredProcedureQuery; import javax.persistence.TypedQuery; -import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.ConfigurableConversionService; +import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -44,10 +46,14 @@ import org.springframework.util.Assert; */ public abstract class JpaQueryExecution { - private static final DefaultConversionService conversionService = new DefaultConversionService(); + private static final ConversionService CONVERSION_SERVICE; static { + + ConfigurableConversionService conversionService = new GenericConversionService(); conversionService.addConverter(JpaResultConverters.BlobToByteArrayConverter.INSTANCE); + + CONVERSION_SERVICE = conversionService; } /** @@ -81,7 +87,8 @@ public abstract class JpaQueryExecution { return result; } - return conversionService.convert(result, requiredType); + return CONVERSION_SERVICE.canConvert(result.getClass(), requiredType) ? CONVERSION_SERVICE.convert(result, + requiredType) : result; } /** 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 ea5de1694..d38d3716d 100644 --- a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java @@ -63,6 +63,8 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; +import com.google.common.base.Optional; + /** * Base integration test class for {@code UserRepository}. Loads a basic (non-namespace) Spring configuration file as * well as Hibernate configuration to execute tests. @@ -1573,6 +1575,20 @@ public class UserRepositoryTests { assertThat(secondPage.getContent(), hasItems(youngest3)); } + /** + * @see DATAJPA-506 + */ + @Test + public void invokesQueryWithWrapperType() { + + flushTestUsers(); + + Optional result = repository.findOptionalByEmailAddress("gierke@synyx.de"); + + assertThat(result.isPresent(), is(true)); + assertThat(result.get(), is(firstUser)); + } + private Page executeSpecWithSort(Sort sort) { flushTestUsers(); 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 42e626eb6..9638f5276 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 @@ -39,6 +39,8 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.transaction.annotation.Transactional; +import com.google.common.base.Optional; + /** * Repository interface for {@code User}s. * @@ -445,10 +447,16 @@ public interface UserRepository extends JpaRepository, JpaSpecifi * @see DATAJPA-551 */ Slice findTop2UsersBy(Pageable page); - + /** * @see DATAJPA-506 */ - @Query(value = "select u.binaryData from User u where u.id = ?", nativeQuery = true) + @Query(value = "select u.binaryData from User u where u.id = ?1", nativeQuery = true) byte[] findBinaryDataByIdNative(Integer id); + + /** + * @see DATAJPA-506 + */ + @Query("select u from User u where u.emailAddress = ?1") + Optional findOptionalByEmailAddress(String emailAddress); }