参数值与预期类型不匹配

Bri*_*ian 7 java hibernate classloader glassfish-4

我有一个列表中的枚举(例如)

enum State
{
   UP,
   DOWN,
   RETRY
};
Run Code Online (Sandbox Code Playgroud)

我的数据库中的列是enum类型.当我尝试通过在查询中设置参数来执行Hibernate查询时setParameter("keyword", State.RETRY);,我收到错误

参数值[RETRY]与预期类型[package.name.State(n/a)]不匹配

在我的域的Glassfish 4.1 server.log中.我正在使用Hibernate 4.3.6.

在寻找对Hibernate的源代码,我看到发生了错误,因为线958-960org.hibernate.jpa.spi.BaseQueryImpl:

private static boolean isValidBindValue(Class expectedType, Object value, TemporalType temporalType) {
        if ( expectedType.isInstance( value ) ) {
            return true;
        }
...
return false;
}
Run Code Online (Sandbox Code Playgroud)

isValidBindValue 返回false,因此我收到消息.

由于这一行,它打印出String相应的enum值:

String.format("Parameter value [%s] did not match expected type [%s (%s)]",
               bind,
               parameterType.getName(),
               extractName( temporalType )
             )
Run Code Online (Sandbox Code Playgroud)

bind目的是通过调用隐式转换为字符串值toString的方法Object,它表示enum State.RETRY.

那我怎么能说服Hibernate这State.RETRY是一个实例State

看起来Hibernate已经更新为JPA 2.1规范,从2013年4月开始,这个规范更加严格:

https://github.com/hibernate/hibernate-orm/commit/84520cd6e36e9207c41528cf9311cae905a86425

该实体注释如下:

@Basic(optional = false)
@Column(name = "state")
@Enumerated(EnumType.String)
private State state;
Run Code Online (Sandbox Code Playgroud)

编辑:

我的RetryState枚举是由EarLibClassLoader.而Query由URLClassLoader EntityManager加载,而由不同的类加载器加载.

unw*_*ich 6

我想主要问题是您试图在数据库端使用枚举数据类型。不建议这样做,因为它通常需要专有的枚举类型,而 JPA 实现(例如 Hibernate)可能无法很好地支持该类型。有关详细信息,请参阅类似问题的答案。

此外,通过注释

@Enumerated(EnumType.String)
Run Code Online (Sandbox Code Playgroud)

您是说您明确希望将该值保存为数据库中的字符串。如果真正的列类型是某种枚举,我预计这会失败。也许 Hibernate 代码更改试图通过强制您使用varchar整数列来防止这些问题。

可能的解决方案:

A)

使用 varchar 列@Enumerated(EnumType.String)或 int 列@Enumerated

二)

您可以尝试通过注释指定枚举列

@Basic(optional = false)
@Column(name = "state", columnDefinition = "enum('UP','DOWN','RETRY')")
@Enumerated(EnumType.String)
private State state;
Run Code Online (Sandbox Code Playgroud)

C)

您可以尝试通过 hibernate XML 映射文件指定枚举类:

<property name="type" column="type" not-null="true">
    <type name="org.hibernate.type.EnumType">
        <param name="enumClass">package.name.State</param>
        <param name="type">12</param>
        <!-- 12 is java.sql.Types.VARCHAR -->
    </type> 
</property>
Run Code Online (Sandbox Code Playgroud)

也可以看看:


Bri*_*ian 1

通过将带有 JPA 注释的类和枚举类放入domain-dir/lib/applib目录中可以修复此问题。您必须将这些类放入domain-dir/lib/applib目录中的 JAR 中,然后使用 asadmin 在部署命令上指定该 jar--libraries jar1,jar2,etc。列出多个 JAR 文件时,请勿在逗号后放置空格。

另外,我有一个具有 EJB 远程接口的通用 JAR,因此我必须将 JPA 类分解到一个新的 JAR 中,并将它们也放在我的applibs目录中。然后,我将带有 EJB 远程接口的 JAR 放入我的 EAR\lib 目录中。

lib/applibs目录中的 JAR由URLClassLoader加载。EAR\lib 中的 JAR 由EARLibClassLoader加载。