Java 休眠连接多个blob
我有多个BLOB,我想彼此连接,以便得到一个连接的BLOB。在此过程中,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
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);
}