blob sql类型的Hibernate验证问题

时间:2013-06-03 07:05:31

标签: java hibernate validation hsqldb liquibase

我收到以下错误:

Caused by: org.hibernate.HibernateException: Wrong column type in PUBLIC.PUBLIC.ALL_TYPES_ENTITIES for column blob1. Found: varbinary, expected: blob(255)
    at org.hibernate.mapping.Table.validateColumns(Table.java:383)

我正在使用liquibase创建表:

        <column name="blob1" type="BLOB">
            <constraints nullable="true"/>
        </column>

java实体有一个字段:

private byte[] blob1;
...
@Basic(fetch = FetchType.LAZY)
@Lob
@Column(name = "blob1")
public byte[] getBlob1() {
    return blob1;
}

我使用hsqldb 2.2.9作为数据库,Hibernate 3.5.0-Final作为JPA提供程序。 hsqldb的Hibernate方言是:

<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>

当liquibase生成表时,liquibase HsqlTypeConverter应该使用VARBINARY作为sql类型。 当Hibernate验证方案时,它认为类型是blob(255),将它与VARBINARY进行比较并抛出异常。

以下是验证表格的代码:

public void validateColumns(Dialect dialect, Mapping mapping, TableMetadata tableInfo) {
    Iterator iter = getColumnIterator();
    while ( iter.hasNext() ) {
        Column col = (Column) iter.next();

        ColumnMetadata columnInfo = tableInfo.getColumnMetadata( col.getName() );

        if ( columnInfo == null ) {
            throw new HibernateException( "Missing column: " + col.getName() + " in " + Table.qualify( tableInfo.getCatalog(), tableInfo.getSchema(), tableInfo.getName()));
        }
        else {
            final boolean typesMatch = col.getSqlType( dialect, mapping ).toLowerCase()
                    .startsWith( columnInfo.getTypeName().toLowerCase() )
                    || columnInfo.getTypeCode() == col.getSqlTypeCode( mapping );
            if ( !typesMatch ) {
                throw new HibernateException(
...

在调试器中,我可以看到抛出异常时,col.sqlType = blob(255)columnInfo.typeName = VARBINARY。出于某种原因,当对{init} col.sqlType调用col.getSqlType( dialect, mapping )时,它会获得blob(255)。 我想我应该在hibernate配置中更新hsqldb dialect。但不确定。 不知道我该怎么做才能解决问题。

2 个答案:

答案 0 :(得分:2)

Liquibase不使用sql BLOB类型用于自2.0版以来在hsqldb中可用的blob。 在hsqldb 1.8.X中,用于blob的sql类型是:varbinary。 为了解决这个问题,我更新了hibernate中使用的hsqldb方言:

public class HSQL_1_8_X_Dialect extends HSQLDialect {

    public HSQL_1_8_X_Dialect() {
        super();

        registerColumnType(Types.BLOB, "varbinary");
        registerColumnType(Types.CLOB, "varchar");
    }
}

<property name="hibernate.dialect" value="com.savdev.datasource.dialect.HSQL_1_8_X_Dialect"/>

它解决了这个问题。另外,我想liquibase应该更新当前的HsqlTypeConverter或添加支持hsqldb 2.X版本的新版本。

答案 1 :(得分:1)

您在验证查询中收到255,因为它是length注释的@Column属性的默认值。

由于HSQLDB同时支持VARBINARYBLOB SQL types,显然Hibernate使用BLOB作为byte[]列的默认SQL映射。

您可以通过指定VARBINARY的{​​{1}}属性明确告诉Hibernate使用columnDefinition

@Column

请注意,列定义可以通过明确指定其长度来更改,如here所述,但通常与@Basic(fetch = FetchType.LAZY) @Lob @Column(name = "blob1", columnDefinition = "VARBINARY") public byte[] getBlob1() { return blob1; } 列相关。