【问题标题】:Hibernate/JPA bug - Not recognizing some strings in a enumHibernate/JPA 错误 - 无法识别枚举中的某些字符串
【发布时间】:2011-09-19 22:46:06
【问题描述】:

我在一个类中有一个枚举,由 Hibernate 映射。映射字段之一是枚举类型,它具有以下值之一 OKNOKNAPNOKNAP 可以按预期工作,但是当类的字段设置为“OK”时,Hibernate 无法映射和检索设置为 null 的值:

java.lang.IllegalArgumentException: Unknown name value for enum class     com.a.b.c.d.Class$Status: OK
    at org.hibernate.type.EnumType.nullSafeGet(EnumType.java:113)

课程有:

private Status status;

@JoinColumn(name = "STATUS")
@Enumerated(EnumType.STRING)
public Status getStatus() {
    return status;
}

public enum Status {
    OK, NOK, NAP;
}

如果我将 OK 更改为 OK2,它可以正常工作。 _OK 也可以。 就我而言,“OK”不是保留名称(就像在这种情况下 uses new 的家伙),因为它编译正确。

谢谢!

更新:

'到目前为止,我解决问题的方法是修改枚举并在数据库中存储'_OK'而不是'OK',如图更多。不是很好的解决方案,但至少可以工作。

public enum Status {
    _OK("OK"), 
    NOK("NOK"), 
    NAP("NAP");

    private String desc;

    private Status(String desc){
        this.desc = desc;
    }

    public String getDesc(){
        return desc;
    }
}

错误报告:

bug report has been filled

【问题讨论】:

  • 您的各种测试似乎都经过深思熟虑。看来你有问题!请通过 hibernate 的 jira 报告,包括您的示例代码。
  • @telm,我正在使用 Hibernate 3.4.0.GA,这可能是问题所在。但是,如果我想升级到 3.5.6 或(3.6.5,最后的最终版本),我需要谨慎,因为这是在许多产品中使用的 Maven pom.xml 上设置的。所以,在此之前我必须进行一些测试。但感谢您的建议。我可能会按照@Bohemian 所说的去做并填写错误请求。
  • FWIW 我用 DataNucleus JPA 尝试了你的示例,对象在所有值上都保持正常,并且所有读回都正常。
  • @telm,@DataNucleus,与 3.6.5.Final 相同的问题。我认为问题出在休眠注释中,当我更改 POM.xml 上的休眠版本时,它并没有从 3.4.0.GA 更改。将在报告之前尝试。

标签: java hibernate exception enums


【解决方案1】:

您遇到的问题是,在您的数据库中,您有除 OK、NOK、NAP 以外的值,并且当您检索记录时,是在您收到异常时,而不是在您持久化时。

从您的异常 com.a.b.c.d.Class$Status: OK2 看来,您的数据库具有该值,因此出现 java.lang.IllegalArgumentException: Unknown name value for enum class 异常。

检查您的表格中的无效值,删除/更正它们,然后重试。

【讨论】:

  • 数据库有OK2值是因为我从OK改为用枚举中的OK2值进行测试。
  • 是的,这就是为什么当您将其更改回 OK 时它会失败,因为 ENUM 值与属性值不对应。这正是您的例外所指出的。如果您修复了这些值,并得到 another 异常,请告诉我。
  • 要重新运行所有测试,我已将要获取的记录设置为“OK”,其余的仍为 null。此外,枚举包含“OK”、“NOK”和“NAP”。我得到以下异常:java.lang.IllegalArgumentException: Unknown name value for enum class com.a.b.c.d.Class$Status: OK at org.hibernate.type.EnumType.nullSafeGet(EnumType.java:113) 还尝试将表中的所有数据库记录设置为 status**='OK',因此没有记录具有 **status**=_null_ 了,但我得到了 **the与上述相同的异常
  • 你为什么用@JoinColumn而不是@Column
  • 好吧,可能是个错误。更正了,但问题仍然存在。您是否看过更新的解决方案,这是一个快速修复但不是很好的解决方案?除此之外,一切都让我相信这是一个错误。
【解决方案2】:

作为另一种解决方法,您可以尝试提供精确的列定义以具有 VARCHAR 列:

@Column(columnDefinition = "VARCHAR(3)")
// @Column(columnDefinition = "VARCHAR2(3)") // VARCHAR2 for Oracle
@Enumerated(EnumType.STRING)
public Status getStatus() {
    return status;
}

public enum Status {
    OK, NOK, NAP;
}

【讨论】:

    【解决方案3】:

    在将 HSQLDB 从 1.8 升级到 2.2.6 后,我遇到了完全相同的问题。对于枚举,Hibernate 创建 CHARACTER 类型的列,这是一个固定长度的列(与 VARCHAR 相反)。它的长度可能确定为最长枚举值的长度。 Hibernate 可以正确生成 INSERT/UPDATE 语句,但是当从表中读取值时,这些较短的值会附加空格。

    因此,HSQLDB 驱动程序似乎没有修剪它们。如果应该,我认为应该为 HSQLDB 提交错误,而不是 Hibernate。但是,如果 HSQLDB 的这种行为与 SQL 标准兼容,那么在读取枚举值时,应该是 Hibernate 的 EnumType 进行修剪。

    【讨论】:

    • 感谢您的洞察力。我在 Hibernate 的 Jira 上填了这个 bug,希望能弄清这个 bug 可能是什么。我正在考虑在 HSQLDB Bug Tracker 上也填写一个,但我可能会等待第一个状态发生一些变化,以便进一步讨论这个主题。
    • 最新的 HSQLDB 兼容 SQL 标准。 CHARACTER(3) 表示如果字符串较短,则用空格填充。其他几个数据库的工作方式相同。
    • 好吧,那不是错误,@fredt。谢谢
    • @lucasarruda,您是否使用 Hibernate 自动生成数据库架构?我在问,因为如果是 Hibernate 生成了固定长度类型的列,那么 Hibernate 应该能够毫无问题地从该列读取,否则 Hibernate 的逻辑将被证明是不一致的,因此包含一个错误。
    • 不,它是由 DBA 创建的。据我记得(因为我不再在我编写该代码的地方工作)该字段由 VARCHAR(3) 定义。这可能就是问题所在。但是,如果 VARCHAR(x) 的字段 x > 3,那不应该也可以工作吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多