在更新到Sping Boot 3.2和Hibernate 6.2之后,枚举值的数据库列类型从整数更改为smallint更多信息在这里。
因此,我们将db列改为smallint。另一方面,Smallint被hibernateMap为short。
因此,我们遇到了基于接口的包含枚举的投影的问题:
public interface MyProjection {
MyEnum getEnum();
}
字符串
因为没有默认的转换器,我们得到这个错误
java.lang.UnsupportedOperationException: Cannot project java.lang.Short to com.bbraun.nemo.enums.MyEnum; Target type is not an interface and no matching Converter found
at org.springframework.data.projection.ProjectingMethodInterceptor.potentiallyConvertResult(ProjectingMethodInterceptor.java:110)
at org.springframework.data.projection.ProjectingMethodInterceptor.invoke(ProjectingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.projection.ProxyProjectionFactory$TargetAwareMethodInterceptor.invoke(ProxyProjectionFactory.java:243)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:249)
型
为了解决这个问题,我尝试添加一个自定义转换器Short-To-Enum:
@Component
final class ShortToEnumConverterFactory implements ConverterFactory<Short, Enum> {
@Override
public <T extends Enum> Converter<Short, T> getConverter(Class<T> targetType) {
return new ShortToEnum(targetType);
}
private static class ShortToEnum<T extends Enum> implements Converter<Short, T> {
private final Class<T> enumType;
public ShortToEnum(Class<T> enumType) {
this.enumType = enumType;
}
@Override
public T convert(Short source) {
return this.enumType.getEnumConstants()[source];
}
}
型
注册通过
@Configuration
...
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new ShortToEnumConverterFactory());
}
...
型
以及像这样将其添加到DefaultConversionService
DefaultConversionService sharedInstance = (DefaultConversionService)DefaultConversionService.getSharedInstance();
sharedInstance.addConverterFactory(new ShortToEnumConverterFactory());
型
不是在修复它
问题是,在ProxyProjectionFactory中创建了DefaultConversionService的新示例,而不是使用sharedInstance:
class ProxyProjectionFactory implements ProjectionFactory, BeanClassLoaderAware {
static final GenericConversionService CONVERSION_SERVICE = new DefaultConversionService();
...
型
此示例不包含mit添加的自定义转换器。
有一段时间使用了sharedInstance,但不管出于什么原因,它被这个commit改变了。
所以我的问题是,有没有可能以任何方式添加一个自定义转换器,由ProxyProjectionFactory使用?
还是应该以一种完全不同的方式来处理这件事?
1条答案
按热度按时间sulc1iza1#
复杂对象转换从不受用于投影的转换服务的影响。转换服务可以调整轻微的转换(long到int),但在任何情况下都不能调整String到复杂对象的转换。
底层实体决定了需要在投影中使用的类型。或者,使用
SpEL
到@Value
,如本答案所述-https://stackoverflow.com/a/70253539/16769477