有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Hibernate/hsqldb 2无法创建Blob列

我试图使用Hibernate 3.5.6从HSQL 2.0数据库加载一个包含字节数据(用@Lob注释)的实体。该实体可以无任何问题地保存,如果它在缓存中(即不需要水合),则可以正常加载。但是,当实体不在缓存中(需要水合)时,我收到以下异常:

Caused by: org.hsqldb.HsqlException: incompatible data type in conversion: from SQL type BLOB to [B, value: instance of org.hsqldb.types.BlobDataID
    at org.hsqldb.error.Error.error(Unknown Source)
    ... 68 more

以下是完整的堆栈跟踪(减去一些特定于域的跟踪)以了解更多上下文:

javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168)
...

Caused by: org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.loader.Loader.doList(Loader.java:2452)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2192)
at org.hibernate.loader.Loader.list(Loader.java:2187)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:452)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1258)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:241)
... 45 more

Caused by: java.sql.SQLSyntaxErrorException: incompatible data type in conversion: from SQL type BLOB to [B, value: instance of org.hsqldb.types.BlobDataID
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.Util.throwError(Unknown Source)
at org.hsqldb.jdbc.JDBCResultSet.getColumnInType(Unknown Source)
at org.hsqldb.jdbc.JDBCResultSet.getBytes(Unknown Source)
at org.hsqldb.jdbc.JDBCResultSet.getBytes(Unknown Source)
at org.hibernate.type.AbstractBynaryType.get(AbstractBynaryType.java:103)
at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:186)
at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:175)
at org.hibernate.type.AbstractType.hydrate(AbstractType.java:105)
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2267)
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1443)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1371)
at org.hibernate.loader.Loader.getRow(Loader.java:1271)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:619)
at org.hibernate.loader.Loader.doQuery(Loader.java:745)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
at org.hibernate.loader.Loader.doList(Loader.java:2449)
... 53 more
Caused by: org.hsqldb.HsqlException: incompatible data type in conversion: from SQL type BLOB to [B, value: instance of org.hsqldb.types.BlobDataID
at org.hsqldb.error.Error.error(Unknown Source)
... 68 more

当我使用Hibernate 3.5.6和HSQL 1.8.0.10时,这个问题没有出现,可能是因为使用了不同的方言(HSQL 1.8不支持Blob列)。我正在使用的Hibernate版本应该支持HSQL 2,我已经检查过它是否正确检测HSQL版本并使用正确的方言。当我使用MySQL时,这个问题也不会发生

该实体有一个Lob列,其设置如下:

@Entity
public class ImageEntity extends IdEntity {

    @Lob
    @Column(name="IMAGE")
    private byte[] imageBytes;
    ...

这是Hibernate/HSQL 2.0错误吗


共 (1) 个答案

  1. # 1 楼答案

    我在JDBCResultSet中发现了这个问题。java(从Sourceforge项目下载的HSQLDB2.0.0)getBytes方法。HSQLDB 2.0支持blob列,其中1.8.*没有,所以这可能是一个他们没有完全更新JDBC实现的bug。getBytes方法的以下修补程序解决了此问题:

    public byte[] getBytes(int columnIndex) throws SQLException {
    
        Type sourceType = resultMetaData.columnTypes[columnIndex-1];
        if (sourceType.isLobType()){
            Blob b = getBlob(columnIndex);
            return b.getBytes(1, (int)b.length());
        }
    
        Object x = getColumnInType(columnIndex, Type.SQL_VARBINARY);
    
        if (x == null) {
            return null;
        }
    
        return ((BinaryData) x).getBytes();
    }
    

    最初的方法是:

    public byte[] getBytes(int columnIndex) throws SQLException {
    
        Object x = getColumnInType(columnIndex, Type.SQL_VARBINARY);
    
        if (x == null) {
            return null;
        }
    
        return ((BinaryData) x).getBytes();
    }