Я столкнулся с некоторыми проблемами в проекте с Spring и Hibernate, когда поток, передаваемый Blob, не закрыт.
Blob blob = Hibernate.getLobCreator(currentSession).createBlob(inputStream, size);
Я не могу использовать такие вещи, как try with resources
, поскольку поток читается только послетранзакция совершается.Я попытался закрыть поток с помощью hibernate @PostPersist
.Он работает в персистентных ситуациях, но вызывает проблемы с Blob, уже освобожденным при CascadeType.MERGE
сценариях.
Один из моих друзей предложил хакерский способ справиться с этим.По сути, его идея заключалась в том, чтобы написать оболочку, которая закрывает поток после завершения чтения.
import java.io.IOException;
import java.io.InputStream;
public class SelfClosingInputStream extends InputStream {
private InputStream inputStream;
public SelfClosingInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public int read() throws IOException {
try {
int val = this.inputStream.read();
if (val != -1) {
return val;
} else {
this.inputStream.close();
return -1;
}
} catch (Exception e) {
this.inputStream.close();
throw e;
}
}
}
Я провел простой тест, и он работает.Я понимаю, что при проверке if может возникнуть проблема с производительностью.Однако я думаю, что в этом есть и другие предостережения.Может кто-то пролить свет на эти?
Blob blob = Hibernate.getLobCreator(currentSession).createBlob(new SelfClosingInputStream(inputStream), size);
PS: я уже опубликовал это здесь при проверке кода, но получил очень мало ответов.Отсюда следует репостинг с некоторыми обновлениями.
ОБНОВЛЕНИЕ:
Получено много отзывов об обзоре кода.Этот ответ , кажется, дает наиболее правильный способ сделать это.
Далее https://commons.apache.org/proper/commons-io/javadocs/api-2.4/org/apache/commons/io/input/AutoCloseInputStream.html дает аналогичную реализацию.