@ConstructorResult с Enum в JPA 2.1
Я понятия не имею, как использовать Enum в типе @ColumnResult при использовании @ConstructorResult из @SqlResultSetMapping
@SqlResultSetMapping(name="DetailAndResult",
classes={
@ConstructorResult(targetClass=DetailAndResult.class, columns={
@ColumnResult(name="id", type= String.class),
@ColumnResult(name="runId", type=Integer.class),
@ColumnResult(name="subRunId", type=Integer.class),
@ColumnResult(name="transactionId", type=Integer.class),
@ColumnResult(name="referenceNumber", type=String.class),
@ColumnResult(name="customerName", type=String.class),
@ColumnResult(name="transactionType", type=TransactionType.class),
@ColumnResult(name="transactionResultStatus", type=String.class)
})
}
)
в приведенной выше конфигурации, имя "actionType "имеет перечисление TransactionType. Как правильно использовать Enum здесь.
если выше - правильный путь, то я получаю это исключение (если я удалю поле Enum, то исключения нет), так что думаю, что должен быть другой способ использовать это.
Caused by: javax.persistence.PersistenceException: org.hibernate.type.SerializationException: could not deserialize
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763) ~[hibernate-entitymanager-4.3.6.Final.jar:4.3.6.Final]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677) ~[hibernate-entitymanager-4.3.6.Final.jar:4.3.6.Final]
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:458) ~[hibernate-entitymanager-4.3.6.Final.jar:4.3.6.Final]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_51]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_51]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_51]
at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_51]
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:333) ~[spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at com.sun.proxy.$Proxy146.getResultList(Unknown Source) ~[na:na]
С hibernateTemplate мы использовали sqlquery.addscalar, и там был способ использовать Enum, используя org.hibernate.type.Type и
TypeLocatorImpl(new TypeResolver()).custom(EnumType.class, params)
Пожалуйста, предложите, будет ли что-то подобное использоваться для @SqlResultSetMapping и @ConstructorResult
3 ответа
Я также столкнулся с этой проблемой и не нашел ничего после довольно обширного поиска. Я зашел так далеко, что посмотрел на исходный код, и насколько я мог судить, вообще не было никакой обработки enums (хотя, конечно, я мог что-то упустить).
В итоге я создал альтернативный конструктор, который взял String для типа enum, а затем передал его в метод valueOf() перечисления.
Например
измените свой @SqlResultSetMapping, чтобы сделать это:
@ColumnResult(name="transactionType", type=String.class),
И тогда в конструкторе вашего класса:
public DetailAndResult(..., String transactionType, ...) {
...
this.transactionType = TransactionType.valueOf(transactionType);
...
}
Это раздражает, что мы должны сделать это, но пока ваше перечисление хранится в виде String в БД (т. Е. Столбец вашей сущности помечается @Enumerated(EnumType.STRING)), это работает.
Наткнулся на недокументированное решение для этого. В типе @ColumnResult
Вы можете поместить спящий UserType, который отображает тип в тип, ожидаемый конструктором. Это работает для гибернации, и я не уверен, что другие реализации JPA поддержали бы это.
Итак, в вашем примере вы бы реализовали пользовательский тип UserType для перечислений и поместили этот класс в @ColumnResult
,
Вы все еще можете использовать @Enumerated(EnumType.STRING) в своем поле объекта,
Мой @SqlResultSetMapping выглядит немного иначе:
@FieldResult(имя = "состояние", столбец = "СОСТОЯНИЕ"),