try*_*its 7 java spring projection spring-boot
我正在尝试使用JPA 投影(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);
}
Run Code Online (Sandbox Code Playgroud)
我想按如下方式使用存储库:
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***
Run Code Online (Sandbox Code Playgroud)
但是,调用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***
Run Code Online (Sandbox Code Playgroud)
返回的TestValue代理对象将该id属性存储为原始byte数组。我希望ProjectingMethodInterceptor最终执行到UUID实例的实际类型转换。查看源代码 ( ProjectingMethodInterceptor.invoke(..):74) 似乎它使用 aConversionService进行转换。我尝试了以下方法:
@Configuration
public class MyApplicationConfig {
@Bean
public ConversionService conversionService() {
DefaultConversionService service = new DefaultConversionService();
service.addConverter(new UUIDConverter());
return service;
}
}
Run Code Online (Sandbox Code Playgroud)
类UUIDConverter实现接口org.springframework.core.convert.converter.Converter<byte[], UUID>。不幸的是,这种方法不起作用,因为 usedProjectingMethodInterceptor是通过ProxyProjectingFactory绕过配置ConversionService并实例化 a DefaultConversionService( ProxyProjectionFactory.ctor():65) 创建的。
我还尝试将注释添加@Convert(converter = UUIDConverter.class)到 中的getId()声明中TestValue,但是,这种方法也不起作用。
我显然可以将方法的返回类型更改getId()为byte[]并UUID在我的应用程序代码中执行实际的转换,但是这种方法感觉不是正确的方法。
问题 1:在JPA Interface Projections 中如何定义自定义类型转换?
问题 2:如果这是不可能的,那么使用确切的方法签名和底层查询来实现上述存储库方法的“Spring 预期”方式是什么。
| 归档时间: |
|
| 查看次数: |
1330 次 |
| 最近记录: |