我有一个带状态列表的枚举(例如)
enum State
{
UP,
DOWN,
RETRY
};
我的数据库中的列是enum类型。当我尝试通过使用setParameter("keyword", State.RETRY);
在查询中设置参数来执行Hibernate查询时,我收到错误
参数值[RETRY]与预期类型不匹配 [package.name.State(n / a)]
在我的域名的Glassfish 4.1 server.log中。我正在使用Hibernate 4.3.6。
在查看Hibernate的源代码时,由于org.hibernate.jpa.spi.BaseQueryImpl
中的第958-960行,我发现错误发生了:
private static boolean isValidBindValue(Class expectedType, Object value, TemporalType temporalType) {
if ( expectedType.isInstance( value ) ) {
return true;
}
...
return false;
}
isValidBindValue
返回false,因此我收到了消息。
由于此行,它打印出String
等效的enum
值:
String.format("Parameter value [%s] did not match expected type [%s (%s)]",
bind,
parameterType.getName(),
extractName( temporalType )
)
通过调用代表bind
的{{1}}上的toString
方法,将Object
对象隐式转换为字符串值。
那我怎么能说服Hibernate enum State.RETRY
是State.RETRY
的一个实例?
看起来Hibernate已更新为JPA 2.1规范,从2013年4月开始,此规范中更严格:
https://github.com/hibernate/hibernate-orm/commit/84520cd6e36e9207c41528cf9311cae905a86425
该实体注释如下:
State
编辑:
我的@Basic(optional = false)
@Column(name = "state")
@Enumerated(EnumType.String)
private State state;
枚举由RetryState
加载。而EarLibClassLoader
由URLClassLoader加载,Query
由不同的类加载器加载。
答案 0 :(得分:2)
我猜主要的问题是你试图在数据库端使用枚举数据类型。建议不要这样做,因为它通常需要专有的枚举类型,而JPA实现可能无法很好地支持它(例如Hibernate)。有关详细信息,请参阅类似问题的this answer。
此外,使用注释
@Enumerated(EnumType.String)
您说您明确要求,该值在数据库中以
可能的解决方案:
A)
使用带有@Enumerated(EnumType.String)
的varchar列或带有@Enumerated
B)
您可以尝试通过注释
指定枚举列@Basic(optional = false)
@Column(name = "state", columnDefinition = "enum('UP','DOWN','RETRY')")
@Enumerated(EnumType.String)
private State state;
<强> 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>
另见:
答案 1 :(得分:0)
通过将带有JPA注释和枚举类的类放入 domain-dir / lib / applib 目录中,可以解决这个问题。您必须将这些类放在 domain-dir / lib / applib 目录中的JAR中,然后使用{{1}使用asadmin在deploy命令上指定jar }。列出多个JAR文件时,请勿在逗号后面放置空格。
另外,我有一个具有EJB远程接口的通用JAR,因此我不得不将我的JPA类分解为新的JAR并将它们放在我的 applibs 目录中也。然后,我将带有EJB远程接口的JAR放入我的EAR \ lib目录。
lib / applibs 目录中的JAR由 URLClassLoader 加载。 EAR \ lib中的JAR由 EARLibClassLoader 加载。
答案 2 :(得分:0)
我在一个项目上遇到了同样的问题,但是经过几次尝试,创建一个表来代替我的枚举更为合理。但是,似乎可以通过使用Jackson来工作