我有一个带有状态列表的枚举(例如)
enum State
{
UP,
DOWN,
RETRY
};
我数据库中的列是枚举类型。当我尝试通过使用 setParameter("keyword", State.RETRY);
在查询中设置参数来执行 Hibernate 查询时,我收到错误
Parameter value [RETRY] did not match expected type [package.name.State (n/a)]
在我的域的 Glassfish 4.1 server.log 中。我正在使用 Hibernate 4.3.6。
在查看 Hibernate 的源代码时,我发现错误是由于 org.hibernate.jpa.spi.BaseQueryImpl
中的 lines 958-960 引起的:
private static boolean isValidBindValue(Class expectedType, Object value, TemporalType temporalType) {
if ( expectedType.isInstance( value ) ) {
return true;
}
...
return false;
}
isValidBindValue
返回 false,因此我收到消息。
由于这一行,它打印出与 enum
值等效的 String
:
String.format("Parameter value [%s] did not match expected type [%s (%s)]",
bind,
parameterType.getName(),
extractName( temporalType )
)
bind
对象通过调用 Object
上的 toString
方法隐式转换为 String 值,它表示 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;
编辑:
我的 RetryState
枚举由 EarLibClassLoader
加载。而 Query
由 URLClassLoader 加载,而 EntityManager
由不同的类加载器加载。
最佳答案
我想主要问题是您正试图在数据库端使用枚举数据类型。不推荐这样做,因为它通常需要 JPA 实现(例如 Hibernate)可能无法很好地支持的专有枚举类型。参见 this answer关于一些细节的类似问题。
进一步,加上注解
@Enumerated(EnumType.String)
您是说您明确希望将该值作为字符串保存在数据库中。如果真正的列类型是某种枚举,我希望这会失败。也许 Hibernate 代码更改试图通过强制您使用 varchar 或 integer 列来防止这些问题。
可能的解决方案:
A)
使用 @Enumerated(EnumType.String)
的 varchar 列或 @Enumerated
的 int 列
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>
另请参阅:
关于java - 参数值与预期类型不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27622045/