Spring data jpa - преобразование пользовательских типов в интерфейсной проекции - PullRequest
1 голос
/ 16 октября 2019

Я пытаюсь реализовать Проецирование на основе интерфейса , но я не могу заставить его работать с моим столбцом пользовательского типа.

Ниже приведен пример того, что я пытаюсь сделать:

Репозиторий:

@Query(value = "SELECT customType from TABLE", nativeQuery = true)
List<TestClass> getResults();

Проекция интерфейса:

public interface TestClass {
  @Convert(converter = MyCustomTypeConverter.class)
  MyCustomType getCustomType();
}

Конвертер:

@Converter
public class MyCustomTypeConverter implements AttributeConverter<MyCustomType, String> {

  @Override
  public String convertToDatabaseColumn(MyCustomType o) {
      // whatever;
  }

  @Override
  public MyCustomType convertToEntityAttribute(String value) {
      // whatever;
  }
}

Когда я вызываю getResults () в репозитории, я получаю списокрезультаты, как и ожидалось, но когда я пытаюсь вызвать getCustomType () для одного из результатов, я получаю исключение:

java.lang.IllegalArgumentException: Projection type must be an interface!
at org.springframework.util.Assert.isTrue(Assert.java:118)
at org.springframework.data.projection.ProxyProjectionFactory.createProjection(ProxyProjectionFactory.java:100)
at org.springframework.data.projection.SpelAwareProxyProjectionFactory.createProjection(SpelAwareProxyProjectionFactory.java:45)
at org.springframework.data.projection.ProjectingMethodInterceptor.getProjection(ProjectingMethodInterceptor.java:131)
at org.springframework.data.projection.ProjectingMethodInterceptor.invoke(ProjectingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.ProxyProjectionFactory$TargetAwareMethodInterceptor.invoke(ProxyProjectionFactory.java:245)

Я обнаружил, что проблема заключается в

org.springframework.data.projection.ProxyProjectionFactory

, который использует

org.springframework.core.convert.support.DefaultConversionService

, в котором явно не зарегистрирован мой пользовательский конвертер типов.

Если я остановлюсь на точке останова в ConversionService и вручную добавлю конвертер во время выполнения, проекция будет работать без проблем.

Итак, вопрос: могу ли я каким-то образом зарегистрировать свой собственный конвертер в ConversionService, используемый Spring jpa во время проекции на основе интерфейса?

РЕДАКТИРОВАТЬ:

Я добавил свой конвертер вDefaultConversionService's sharedInstanceв InitializingBean, как показано ниже, и это сработало.

@Component
public class DefaultConversionServiceInitializer implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
        DefaultConversionService conversionService = (DefaultConversionService) DefaultConversionService.getSharedInstance();
        conversionService.addConverter(new MyCustomTypeConverter());
    }
}

1 Ответ

0 голосов
/ 17 октября 2019

ConversionService используется DefaultConversionService.getSharedInstance().

Таким образом, вы сможете получить к нему доступ и добавить свой конвертер.

...