Java 休眠连接多个blob

Java 休眠连接多个blob,java,hibernate,stream,blob,Java,Hibernate,Stream,Blob,我有多个BLOB,我想彼此连接,以便得到一个连接的BLOB。在此过程中,blob的内容可能不会存储在内存中 我的第一个想法是像这样合并流: long size = blobs.get(0).length(); InputStream res = blobs.get(0).getBinaryStream(); for (int i = 1; i < blobs.size(); i++){ res = Stream.concat(res, blobs.get(i).getBinaryS

我有多个BLOB,我想彼此连接,以便得到一个连接的BLOB。在此过程中,blob的内容可能不会存储在内存中

我的第一个想法是像这样合并流:

long size = blobs.get(0).length();
InputStream res = blobs.get(0).getBinaryStream();
for (int i = 1; i < blobs.size(); i++){
    res = Stream.concat(res, blobs.get(i).getBinaryStream());
    size += blobs.get(i).length();
}
Blob blob = Hibernate.getLobCreator(session).createBlob(res, size);
pipeInputStream
仅将一个流的内容导入另一个流:

private void pipeInputStream (final InputStream is, final OutputStream os) throws IOException {
    final int buffSize = 128000;
            
    int n;
    final byte[] buff = new byte[buffSize];
    while ((n = is.read(buff)) >= 0){
        os.write(buff, 0, n);
}
)

但是,这会产生以下例外情况:

java.lang.UnsupportedOperationException:无法操纵Blob创建会话

此外,我怀疑BLOB仍然会暂时将整个内容存储在内存中


第三次尝试时,我尝试使用自定义的
InputStream

/**
 * Combines multiple streams into one
 */
public class JoinedInputStream extends InputStream {

    private List<InputStream> parts;

    private List<InputStream> marked;

    public JoinedInputStream(final List<InputStream> parts) {
        this.parts = parts;
    }

    @Override
    public int read() throws IOException {

        int res = -1;
        while (res == -1 && parts.size() > 0) {
            try {
                if ((res = parts.get(0).read()) == -1) {
                    // The stream is done, so we won't try to read from it again
                    parts.remove(0);
                }
            } catch (IOException e) {
                e.printStackTrace();
                throw e;
            }
        }
        return res;
    }

    @Override
    public synchronized void reset() throws IOException {
        parts = new ArrayList<>(marked);
        if (parts.size() > 0) {
            parts.get(0).reset();
        }
    }

    @Override
    public synchronized void mark(final int readlimit) {
        marked = new ArrayList<>(parts);
        if (marked.size() > 0)
            marked.get(0).mark(readlimit);
    }

    @Override
    public boolean markSupported() {
        return true;
    }

    @Override
    public void close() throws IOException {
        super.close();
        for (final InputStream part : parts) {
            part.close();
        }
        parts = new ArrayList<>();
        marked = new ArrayList<>();
    }
}
/**
*将多个流合并为一个流
*/
公共类JoinedInputStream扩展InputStream{
私人零件清单;
标明私人名单;
公共JoinedInputStream(最终列出部件){
这一部分=部分;
}
@凌驾
public int read()引发IOException{
int res=-1;
而(res==-1&&parts.size()>0){
试一试{
if((res=parts.get(0.read())=-1){
//流已完成,因此我们不再尝试从中读取
零件。移除(0);
}
}捕获(IOE异常){
e、 printStackTrace();
投掷e;
}
}
返回res;
}
@凌驾
public synchronized void reset()引发IOException{
零件=新阵列列表(已标记);
如果(parts.size()>0){
parts.get(0.reset();
}
}
@凌驾
公共同步无效标记(最终整型读取限制){
标记=新阵列列表(零件);
如果(标记为.size()>0)
marked.get(0).mark(readlimit);
}
@凌驾
公共布尔标记受支持(){
返回true;
}
@凌驾
public void close()引发IOException{
super.close();
用于(最终输入流部分:部分){
部分。关闭();
}
零件=新的ArrayList();
已标记=新的ArrayList();
}
}
然后可以这样连接BLOB(不要介意不必要的函数,它们还有其他用途):

@覆盖
公共Blob createBlobForHibernate(最终会话、最终输入流、最终长长度){
最终LobCreator lc=Hibernate.getLobCreator(会话);
返回lc.createBlob(流,长度);
}
@凌驾
公共Blob createBlobForHibernate(最终会话、最终列表流、最终长长度){
最终加入的InputStream=新加入的InputStream(流);
返回createBlobForHibernate(会话、连接、长度);
}
@凌驾
公共Blob joinBlobsForHibernate(最终会话会话,最终列表Blob)抛出SQLException{
长长度=0;
列表流=新的ArrayList(blobs.size());
用于(最终水滴水滴:水滴){
长度+=blob.length();
add(blob.getBinaryStream());
}
返回createBlobForHibernate(会话、流、长度);
}
但是,这会导致以下错误(在将新创建的实体与连接的BLOB持久化时):

原因:java.sql.SQLException:LOB Lese-/schreibfunkationen aufgerufen,während ein ander Lese-/Schreibvorgang ausgeführt wird:getBytes() 位于oracle.jdbc.driver.T4CConnection.getBytes(T4CConnection.java:3200) 位于oracle.sql.BLOB.getBytes(BLOB.java:391) 位于oracle.jdbc.driver.OracleBlobInputStream.needBytes(OracleBlobInputStream.java:166) ... 还有101个

或以英文:

在另一个读/写过程中调用Lob读/写函数:getBytes()

我已经尝试过将
hibernate.temp.use\u jdbc\u metadata\u defaults
设置为
false
(正如文章中建议的那样)-事实上,我们已经预先设置了这个属性,但它没有任何帮助

/**
 * Combines multiple streams into one
 */
public class JoinedInputStream extends InputStream {

    private List<InputStream> parts;

    private List<InputStream> marked;

    public JoinedInputStream(final List<InputStream> parts) {
        this.parts = parts;
    }

    @Override
    public int read() throws IOException {

        int res = -1;
        while (res == -1 && parts.size() > 0) {
            try {
                if ((res = parts.get(0).read()) == -1) {
                    // The stream is done, so we won't try to read from it again
                    parts.remove(0);
                }
            } catch (IOException e) {
                e.printStackTrace();
                throw e;
            }
        }
        return res;
    }

    @Override
    public synchronized void reset() throws IOException {
        parts = new ArrayList<>(marked);
        if (parts.size() > 0) {
            parts.get(0).reset();
        }
    }

    @Override
    public synchronized void mark(final int readlimit) {
        marked = new ArrayList<>(parts);
        if (marked.size() > 0)
            marked.get(0).mark(readlimit);
    }

    @Override
    public boolean markSupported() {
        return true;
    }

    @Override
    public void close() throws IOException {
        super.close();
        for (final InputStream part : parts) {
            part.close();
        }
        parts = new ArrayList<>();
        marked = new ArrayList<>();
    }
}
@Override
public Blob createBlobForHibernate(final Session session, final InputStream stream, final long length) {
    final LobCreator lc = Hibernate.getLobCreator(session);
    return lc.createBlob(stream, length);
}
@Override
public Blob createBlobForHibernate(final Session session, final List<InputStream> streams, final long length) {
    final InputStream joined = new JoinedInputStream(streams);
    return createBlobForHibernate(session, joined, length);
}
@Override
public Blob joinBlobsForHibernate(final Session session, final List<Blob> blobs) throws SQLException {

    long length = 0;
    List<InputStream> streams = new ArrayList<>(blobs.size());
    for (final Blob blob : blobs) {
        length += blob.length();
        streams.add(blob.getBinaryStream());
    }
    return createBlobForHibernate(session, streams, length);
}