【问题标题】:@ConstructorResult with Enum in JPA 2.1JPA 2.1 中带有枚举的 @ConstructorResult
【发布时间】:2014-11-02 12:38:41
【问题描述】:

在使用@SqlResultSetMapping 的@ConstructorResult 时,我不知道如何在@ColumnResult 类型中使用枚举

@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

【问题讨论】:

    标签: spring hibernate jpa jpa-2.1 sqlresultsetmapping


    【解决方案1】:

    我也遇到了这个问题,经过相当广泛的搜索后没有找到任何东西。我已经查看了源代码,据我所知,根本没有任何类型的枚举处理(当然我可能会遗漏一些东西)。

    我最终做的是创建一个替代构造函数,它接受枚举类型的字符串,然后将其传递给枚举的 valueOf() 方法。

    例如

    更改您的 @SqlResultSetMapping 以执行此操作:

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

    然后在你的类的构造函数中:

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

    我们必须这样做很烦人,但只要您的枚举作为字符串存储在数据库中(即您的实体上的列使用@Enumerated(EnumType.STRING) 进行注释),它就可以工作。

    【讨论】:

    • 如果您将值存储为整数而不是字符串,TransactionType.values()[transactionType] 也可以。
    【解决方案2】:

    遇到了一个未记录的解决方案。在@ColumnResult 的类型中,您可以放置​​一个休眠UserType,它映射构造函数所期望的类型中的类型。这适用于休眠,我不确定其他 JPA 实现是否支持这一点。

    因此,在您的示例中,您将为枚举实现自定义 UserType 并将该类放在 @ColumnResult 中。

    【讨论】:

    • 你能举个例子吗?
    【解决方案3】:

    您仍然可以在您的实体字段上使用@Enumerated(EnumType.STRING),

    我的@SqlResultSetMapping 看起来有点不同:

    @FieldResult(name="state", column="STATE"),

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-07
      • 1970-01-01
      • 2012-08-22
      相关资源
      最近更新 更多