为啥在读取数据库 hsqldb 中的 blob 时抛出 java.lang.IndexOutOfBoundsException

Posted

技术标签:

【中文标题】为啥在读取数据库 hsqldb 中的 blob 时抛出 java.lang.IndexOutOfBoundsException【英文标题】:Why throwing java.lang.IndexOutOfBoundsException when reading blob in the database hsqldb为什么在读取数据库 hsqldb 中的 blob 时抛出 java.lang.IndexOutOfBoundsException 【发布时间】:2015-06-09 10:03:49 【问题描述】:

嗨。我正在使用以下代码将 blob 写入服务器端的数据库。



    @Override
    public void write(TypeHandlerContext context, ResultSet resultSet, Object value) 
        int column = context.getColumn();
        LargeObject lo = (LargeObject)value;
        if(lo == null) 
            try 
                resultSet.updateNull(column);
             catch(SQLException e) 
                throw new RuntimeException(e);
            
         else 
            InputStream is = lo.getInputStream();
            try 
                if(is == null) 
                    Reader r = lo.getReader();
                    if(r == null) 
                        resultSet.updateNull(column);
                        return;//empty Large object
                    
                    is = new ReaderInputStream(r, "UTF-8");
                 
                resultSet.updateBlob(column, is, lo.getLength());
             catch(Exception e) 
                Throwables.throwAsUndeclarable(e);
             finally 
                Tools.closeSilent(is);
            
        
    

使用以下代码读取 blob:



    @Override
    public LargeObject read(TypeHandlerContext context, ResultSet resultSet) 
        try 
            Blob blob = resultSet.getBlob(context.getColumn());
            if(blob == null) 
                return null;
            
            final long len = blob.length();
            final byte[] bytes = readBytes((int)len, blob);
            return new ByteArrayLargeObject(bytes, true, false);
         catch(Exception e) 
            Throwables.throwAsUndeclarable(e);
            return null;
        
    

    private byte[] readBytes(int len, Blob blob) throws Exception 
        try 
            return blob.getBytes(1l, len);
         catch(SQLFeatureNotSupportedException e) 
            InputStream is = blob.getBinaryStream();
            try 
                return IOUtils.toByteArray(is, len);
             finally 
                Tools.closeSilent(is);
            
        
    

Blob 包含下一个测试文本:

和( gt( 场(“sinSystems.childsCount”), 参数(0,“整数”) ), security.checkAccessForTarget("sinSystems.target", "sinSystems.targetType") )

我已经在 oracle 和 postresql 上测试成功,但是在 hsqldb 上测试失败并出现异常:



    Caused by: java.lang.IndexOutOfBoundsException: Index out of bounds: 0 >= 0
        at org.hsqldb.lib.HsqlArrayList.get(Unknown Source)
        at org.hsqldb.persist.LobStoreMem.getBlockBytes(Unknown Source)
        at org.hsqldb.persist.LobManager.getBytesNormal(Unknown Source)
        at org.hsqldb.persist.LobManager.getBytes(Unknown Source)
        at org.hsqldb.Session.performLOBOperation(Unknown Source)
        at org.hsqldb.Session.execute(Unknown Source)
        at org.hsqldb.types.BlobDataID.getBytes(Unknown Source)
        at org.hsqldb.jdbc.JDBCBlobClient.getBytes(Unknown Source)
        at ru.kih.sin.db.types.LargeObjectHandler.readBytes(LargeObjectHandler.java:100)
        at ru.kih.sin.db.types.LargeObjectHandler.read(LargeObjectHandler.java:44)
        at ru.kih.sin.db.types.LargeObjectHandler.read(LargeObjectHandler.java:27)
        at ru.kih.sql.types.NullValueWrapper.read(NullValueWrapper.java:24)
        at ru.kih.sql.types.TypeHandlerWrapper.read(TypeHandlerWrapper.java:74)
        at ru.kih.sql.types.TypeConverter.read(TypeConverter.java:48)
        at ru.kih.sin.model.impl.ObjectReadFunction.apply(ObjectReadFunction.java:119)
        at ru.kih.sin.model.impl.ObjectHandler.handle(ObjectHandler.java:41)
        at ru.kih.sin.model.impl.ObjectHandler.handle(ObjectHandler.java:16)
        at ru.kih.sql.query.handlers.SimpleSelect.handle(SimpleSelect.java:63)
        at ru.kih.sql.query.QueryHelper$UnsafeFunctionImpl.apply(QueryHelper.java:39)
        at ru.kih.sql.query.QueryHelper$UnsafeFunctionImpl.apply(QueryHelper.java:25)
        at ru.kih.sql.query.QueryContext.runIn(QueryContext.java:479)
        at ru.kih.sql.query.QueryContext.run(QueryContext.java:228)
        at ru.kih.sql.query.QueryContext.run(QueryContext.java:212)
        at ru.kih.sql.query.QueryContext.call(QueryContext.java:242)
        at ru.kih.sql.query.QueryHelper.query(QueryHelper.java:57)
        at ru.kih.sin.model.impl.SelectLobFunction.apply(SelectLobFunction.java:62)
        at ru.kih.sin.model.impl.SelectLobFunction.apply(SelectLobFunction.java:24)
        at ru.kih.sql.query.QueryContext.runIn(QueryContext.java:479)
        at ru.kih.sql.query.QueryContext.run(QueryContext.java:228)
        at ru.kih.sql.query.QueryContext.run(QueryContext.java:212)
        at ru.kih.sql.query.QueryContext.call(QueryContext.java:242)
        at ru.kih.sin.model.impl.ModelImpl.lambda$loadLob$8(ModelImpl.java:280)
        at ru.kih.sin.model.impl.ModelImpl$$Lambda$16/26663026.call(Unknown Source)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at ru.kih.sin.model.impl.ModelImpl.loadLob(ModelImpl.java:285)
        ... 48 more

调试器可以看到blob.getLength()大于0。

使用驱动程序 hsqldb-2.3.1 连接到数据库

告诉我有什么问题?

P.S.对不起我的英语))

【问题讨论】:

LargeObjectHandler.java 的第 100 行是哪一行? 返回 blob.getBytes(1l, len);在方法“private byte[] readBytes(int len, Blob blob) throws Exception” 我尝试使用代码 InputStream is = blob.getBinaryStream();尝试 返回 IOUtils.toByteArray(is, len); 最后 Tools.closeSilent(is); 但得到了同样的异常 【参考方案1】:

编写 blob 的代码不完整。您必须在resultSet.updateBlob(...) 之后调用resultSet.updateRow()

最好使用最新版本的 HSQLDB,目前为 2.3.2 和 2.3.3(候选版本)。

【讨论】:

此代码是一个代码块处理程序。还有其他类型的其他处理程序。而resultSet.updateRow() 稍后调用【参考方案2】:

答案已关闭。方法public void write(TypeHandlerContext context, ResultSet resultSet, Object value) 的行Tools.closeSilent(is); 中的问题。它在调用resultSet.updateRow() 之前关闭InputStream

【讨论】:

以上是关于为啥在读取数据库 hsqldb 中的 blob 时抛出 java.lang.IndexOutOfBoundsException的主要内容,如果未能解决你的问题,请参考以下文章

HSQLDB - 如何设置 .lobs 文件编码?

HSQL 数据库大小

使用 spring 数据源更改 HSQLDB 上的 blob 大小

使用 Hibernate 更新 HSQLDB 上的 LOB/BLOB 值会产生数据异常

如何将 sqlite 文件中的 blob 数据读取为可读格式?

使用 HSQLDB 清除 .lobs 文件的推荐方法