具有UUID的Spring接口投影

时间:2018-06-25 17:44:25

标签: java spring spring-boot projection

我正在尝试使用JPA Projection(Spring v1.5.9.RELEASE)从JpaRepository返回自定义类型,如下所示(MCVE):

@Repository
public interface TestRepository extends JpaRepository<Void, Void> {

    public interface TestValue {
        UUID getId();
        int getNum();
    }

    @Query(value = "SELECT :id as id, 1 as num", nativeQuery = true)
    List<TestValue> getTestValues(@Param("id") UUID id);

}

我想按如下方式使用存储库:

List<TestValue> testValues = testRepository.getTestValues(UUID.randomUUID());
int num = testValues.get(0).getNum(); // Returns 1 as expected
UUID id = testValues.get(0).getId(); // ***Fails with an exception***

但是,调用getId()失败,但出现以下异常:

java.lang.IllegalArgumentException: Projection type must be an interface!
    at org.springframework.util.Assert.isTrue(Assert.java:92) ~[spring-core-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.data.projection.ProxyProjectionFactory.createProjection(ProxyProjectionFactory.java:110) ~[spring-data-commons-1.13.9.RELEASE.jar:?]
    at org.springframework.data.projection.SpelAwareProxyProjectionFactory.createProjection(SpelAwareProxyProjectionFactory.java:42) ~[spring-data-commons-1.13.9.RELEASE.jar:?]
    at org.springframework.data.projection.ProjectingMethodInterceptor.getProjection(ProjectingMethodInterceptor.java:126) ~[spring-data-commons-1.13.9.RELEASE.jar:?]
    at org.springframework.data.projection.ProjectingMethodInterceptor.invoke(ProjectingMethodInterceptor.java:76) ~[spring-data-commons-1.13.9.RELEASE.jar:?]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.data.projection.ProxyProjectionFactory$TargetAwareMethodInterceptor.invoke(ProxyProjectionFactory.java:264) ~[spring-data-commons-1.13.9.RELEASE.jar:?]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:56) ~[spring-data-commons-1.13.9.RELEASE.jar:?]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at com.sun.proxy.$Proxy199.getId(Unknown Source) ~[?:?]
    at ***my.company***

返回的TestValue代理对象将id属性存储为原始byte数组。我希望ProjectingMethodInterceptor最终执行对UUID实例的实际类型转换。查看源代码(ProjectingMethodInterceptor.invoke(..):74),似乎它使用ConversionService进行转换。我尝试了以下方法:

@Configuration  
public class MyApplicationConfig {

    @Bean
    public ConversionService conversionService() {
        DefaultConversionService service = new DefaultConversionService();
        service.addConverter(new UUIDConverter());
        return service;
    }
}

UUIDConverter实现接口org.springframework.core.convert.converter.Converter<byte[], UUID>。不幸的是,该方法不起作用,因为通过ProjectingMethodInterceptor创建了使用过的ProxyProjectingFactory,它绕过了配置的ConversionService并实例化了DefaultConversionService({ {1}}。

我还尝试将注释ProxyProjectionFactory.ctor():65添加到@Convert(converter = UUIDConverter.class)中的getId()声明中,但是,此方法也不起作用

我显然可以将TestValue方法的返回类型更改为getId(),并在应用程序代码中实际转换为byte[],但是这种方法并不适合的方法。

  

问题1:    JPA接口投影中如何定义自定义类型转换?

     

问题2:    如果不可能,那么使用上述确切方法签名和基础查询来实现上述存储库方法的“春季计划”方式是什么。

0 个答案:

没有答案