Hibernate/hsqldb 2 无法水合 Blob 列
Posted
技术标签:
【中文标题】Hibernate/hsqldb 2 无法水合 Blob 列【英文标题】:Hibernate/hsqldb 2 Cannot Hydrate Blob Column 【发布时间】:2011-02-17 19:52:55 【问题描述】:我正在尝试使用 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】:我在 JDBCResultSet.java(从 Sourceforge 项目下载的 HSQLDB 2.0.0)getBytes 方法中发现了问题。 HSQLDB 2.0 支持 1.8.* 不支持的 blob 列,因此这可能是他们尚未完全更新其 JDBC 实现的错误。 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();
【讨论】:
感谢您报告此事。 2.0.1 的快照 jar 现在可以在 hsqldb.org/support 获得并修复。以上是关于Hibernate/hsqldb 2 无法水合 Blob 列的主要内容,如果未能解决你的问题,请参考以下文章
确保更新发生在 Hibernate/HSQLDB 中的并发锁定?
使用本机 SQL 创建表适用于 Hibernate/HSQLDB,插入失败。为啥?