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

标签 java hibernate classloader glassfish-4

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

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.RETRYState 的一个实例?

看起来 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 代码更改试图通过强制您使用 varcharinteger 列来防止这些问题。

可能的解决方案:

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/

相关文章:

java - 使用 includeFrom 属性关联 SmartGwt 数据源的问题

java - Soap:使用 WSDL2Java 设置超时

java - 如何在 Hibernate 中使用具有 ManyToMany 关联的嵌套对象正确分页?

java - 披萨课。添加一个名为 setOfToppings 的集合作为属性。使用Java

java - 将具有相同值的数组添加到 HashSet 会导致重复项

hibernate - 何时使用 Hibernate 投影?

java - Spring JPA 对存储库的数据扫描不起作用

java - 使用 Spring Boot 2 的 PropertiesLauncher(并运行 WAR 存档)

java - 配置 JBOss 缓存以在 JBoss 服务器 4.2.3.GA 上运行

java - 如何在运行时动态加载不同项目中的类和库