HSQL + Hibernate 异常:错误的列类型:发现:double,预期:float

HSQL + Hibernate Exception: Wrong column type: Found: double, expected: float

我将内存中的 HSQL (HSQLDB) 与 Hibernate 一起用于我所有的单元测试,因为它非常快。我有一个 table,其列定义如下:

float qw;

休眠启动时,出现以下错误:

org.hibernate.HibernateException: Wrong column type in MyTable for column qw. 
Found: double, expected: float

当列声明为 float 时,为什么找到 double

这是由于一系列不幸事件造成的。

  1. 问题始于HSQLDB不支持 float 数据类型。 (呃?是的,我知道,但是 文档 这里.)

  2. 由于 HSQLDB 确实如此,问题开始变得难看 当您指定 float 列时,不仅仅是 fail,而是 默默地将其重新解释为 double,假装 毫无戒心的程序员认为一切顺利。所以,在你的 create table 语句,您可以将列的类型指定为 float,HSQLDB 会成功,但它只是在骗你, 因为如果您稍后查询该列的类型,您会发现 它是 double,而不是 float

  3. 然后,稍后,hibernate 发现此列为 double,而它 期望它是 float,它不够聪明,无法利用这个事实 float 可从 double 分配 。每个人都知道 doublefloat 好,所以 hibernate 实际上应该 高兴 它找到了一个 double while 它所需要的只是一个 float,对吧? --但是不,hibernate 不会有任何 那:当它期望 float 时,只有 float 会做。

  4. 然后,hibernate 有一件有趣的事据说有 对 HSQLDB 的内置支持,事实证明它包括一个 class org.hibernate.dialect.HSQLDialect, 但是 方言不关心你的花车。 所以,他们不关心 相信数据类型不兼容是一个方言问题?他们 从来没有用花车测试过它?我不知道该怎么想,但是 事情的真相是 HSQLDB 的休眠方言确实 未针对此问题提供任何更正。

那么,我们能做什么呢?

该问题的一个可能解决方案是为 HSQLDB 创建我们自己的休眠方言,我们在其中纠正了这种差异。

过去我遇到过 MySQL 和 booleanbit 的类似问题(参见这个问题:"Found: bit, expected: boolean" after Hibernate 4 upgrade)所以对于 HSQLDB 我解决了通过为休眠声明我自己的 HSQLDB 方言,floatdouble 的问题:

/**
 * 'Fixed' HSQL Dialect.
 *
 * PEARL: HSQL seems to have a problem with floats.  We remedy this here.
 * See 
 *
 * PEARL: this class must be public, not package-private, and it must have a 
 * public constructor, otherwise hibernate won't be able to instantiate it.
 */
public class FixedHsqlDialect extends HSQLDialect
{
    public FixedHsqlDialect()
    {
        registerColumnType( java.sql.Types.FLOAT, "double" );
    }
}

并按如下方式使用它:

ejb3cfg.setProperty( "hibernate.dialect", FixedHsqlDialect.class.getName() );
    //Instead of: org.hibernate.dialect.HSQLDialect.class.getName();