java 参数值与预期类型不匹配

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27622045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 12:08:23  来源:igfitidea点击:

Parameter value did not match expected type

javahibernateclassloaderglassfish-4

提问by Brian

I have an enum with a list of states (e.g.)

我有一个带有状态列表的枚举(例如)

enum State
{
   UP,
   DOWN,
   RETRY
};

The column in my database is of type enum. When I try to execute a Hibernate query by setting the parameter in the query using setParameter("keyword", State.RETRY);, I receive the error of

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

Parameter value [RETRY] did not match expected type [package.name.State (n/a)]

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

In my Glassfish 4.1 server.log for my domain. I am using Hibernate 4.3.6.

在我的域的 Glassfish 4.1 server.log 中。我正在使用休眠 4.3.6。

In looking at the source code for Hibernate, I see the error occurs because of lines 958-960in org.hibernate.jpa.spi.BaseQueryImpl:

在寻找对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;
}

isValidBindValuereturns false and thus I get the message.

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

It prints out the Stringequivalent of the enumvalue because of this line:

由于这一行,它打印出String等效的enum值:

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

The bindobject is implicitly converted to the String value by calling the toStringmethod on the Objectwhich represents the enum State.RETRY.

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

So how I can I convince Hibernate that State.RETRYis an instance of State?

那么我怎样才能说服 HibernateState.RETRY是一个实例State呢?

It looks like Hibernate updated to the JPA 2.1 spec which is more strict in this commit from April 2013:

看起来 Hibernate 更新到了 JPA 2.1 规范,从 2013 年 4 月开始,该规范在此提交中更加严格:

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

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

The entity is annotated as follows:

实体注释如下:

@Basic(optional = false)
@Column(name = "state")
@Enumerated(EnumType.String)
private State state;

Edit:

编辑:

My RetryStateenum is loaded by the EarLibClassLoader. Whereas Queryis loaded by the URLClassLoader and the EntityManageris loaded by a different class loader.

我的RetryState枚举由EarLibClassLoader. 而Query由 URLClassLoaderEntityManager加载,而由不同的类加载器加载。

采纳答案by Brian

This was fixed by placing the classes with the JPA annotations and enum classes into the domain-dir/lib/applibdirectory. You have to place these classes in a JAR in the domain-dir/lib/applibdirectory and then specify the jar on the deploy command with asadmin using the --libraries jar1,jar2,etc. Do not place a space after the comma when listing multiple JAR files.

这是通过将带有 JPA 注释的类和枚举类放入domain-dir/lib/applib目录来解决的。您必须将这些类放在domain-dir/lib/applib目录中的 JAR 中,然后使用--libraries jar1,jar2,etc. 列出多个 JAR 文件时,不要在逗号后放置空格。

Also, I had a common JAR that had EJB remote interfaces, so I had to break out my JPA classes into a new JAR and place them in my applibsdirectory also. I then put the JAR with the EJB remote interfaces into my EAR\lib directory.

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

The JARs in the lib/applibsdirectory are loaded by the URLClassLoader. The JARs in the EAR\lib are loaded by the EARLibClassLoader.

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

回答by unwichtich

I guess the main problem is that you are trying to use an enum datatype on the database side. This is not recommended because it often requires an proprietary enum type which may not be well supported by the JPA implementation (e.g. Hibernate). See this answeron a similar question for some details.

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

Further, with the annotation

此外,通过注释

@Enumerated(EnumType.String)

you are saying that you explicitly want, that the value is saved as a Stringin the database. I would expect that this fails if the real column type is some enum. Maybe the Hibernate code changes are trying to prevent these problems by forcing you to use either varcharor integercolumns.

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

Possible solutions:

可能的解决方案:

A)

一个)

Use a varchar column with @Enumerated(EnumType.String)or an int column with @Enumerated

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

B)

乙)

You can try to specify the enum column via the annotation

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

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

C)

C)

You can try to specify your enum class via an hibernate XML mapping file:

您可以尝试通过休眠 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>

See also:

也可以看看: