2014-09-09 5 views
3

Я не имея ни малейшего представления, как использовать Enum в @ColumnResult Тип при использовании @ConstructorResult из @SqlResultSetMapping@ConstructorResult с Enum в JPA 2.1

@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) 

       }) 
     } 
) 

в описанной выше конфигурации, имя «transactionType» имеет TransactionType Enum , Каков правильный способ использования 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

ответ

0

Пришел к решению без документов для этого. В типе @ColumnResult вы можете разместить hibernate UserType, который отображает тип типа, который ожидает конструктор. Это работает для спящего режима, и я не уверен, что другие реализации JPA поддержат это.

В этом примере вы бы использовали пользовательский UserType для перечислений и помещали этот класс в @ColumnResult.

3

Я также столкнулся с этой проблемой и ничего не нашел после довольно обширного поиска. Я дошел до исходного кода, и насколько я мог судить о том, что для перечислений вообще не было никакой обработки (хотя, конечно, я мог чего-то упустить).

В результате я создал альтернативный конструктор, который использовал String для типа перечисления, а затем передал его в метод valueOf() перечисления.

E.g.

изменить @SqlResultSetMapping, чтобы сделать это:

@ColumnResult(name="transactionType", type=String.class), 

, а затем в конструкторе класса:

public DetailAndResult(..., String transactionType, ...) { 
    ... 
    this.transactionType = TransactionType.valueOf(transactionType); 
    ... 
} 

Это раздражает, что мы должны сделать это, но до тех пор, как ваше перечисление хранится как строка в db (т. е. столбец на вашей сущности аннотируется с @Enumerated (EnumType.STRING)), он работает.

+0

И если вы храните свое значение как целое число, а не строку, 'TransactionType.values ​​() [transactionType]' работает тоже. – Jules