#1423 - Close resources - InputStream of entity bean properties of File type

This commit is contained in:
rob bygrave committed 2018-06-14 00:04:43 +12:00
1 parent c088cfa339
commit 50593a7f9d
7 files changed
+197 -26

No files matched your search

@@ -2,11 +2,16 @@ package io.ebeaninternal.server.persist;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.api.SpiProfileTransactionEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* A batched statement that is held in BatchedPstmtHolder. It has a list of
@@ -17,6 +22,8 @@ import java.util.ArrayList;
*/
public class BatchedPstmt implements SpiProfileTransactionEvent {
private static final Logger log = LoggerFactory.getLogger(BatchedPstmt.class);
/**
* The underlying statement.
*/
@@ -40,6 +47,8 @@ public class BatchedPstmt implements SpiProfileTransactionEvent {
private int[] results;
private List<InputStream> inputStreams;
/**
* Create with a given statement.
*/
@@ -117,16 +126,19 @@ public class BatchedPstmt implements SpiProfileTransactionEvent {
}
private void executeAndCheckRowCounts() throws SQLException {
try {
results = pstmt.executeBatch();
if (results.length != list.size()) {
String s = "results array error " + results.length + " " + list.size();
throw new SQLException(s);
}
results = pstmt.executeBatch();
if (results.length != list.size()) {
String s = "results array error " + results.length + " " + list.size();
throw new SQLException(s);
}
// check for concurrency exceptions...
for (int i = 0; i < results.length; i++) {
list.get(i).checkRowCount(results[i]);
// check for concurrency exceptions...
for (int i = 0; i < results.length; i++) {
list.get(i).checkRowCount(results[i]);
}
} finally {
closeInputStreams();
}
}
@@ -148,4 +160,23 @@ public class BatchedPstmt implements SpiProfileTransactionEvent {
public int[] getResults() {
return results;
}
/**
* Register any inputStreams that should be closed after execution.
*/
public void registerInputStreams(List<InputStream> inputStreams) {
this.inputStreams = inputStreams;
}
private void closeInputStreams() {
if (inputStreams != null) {
for (InputStream inputStream : inputStreams) {
try {
inputStream.close();
} catch (IOException e) {
log.warn("Error closing inputStream ", e);
}
}
}
}
}
@@ -39,6 +39,15 @@ public class BatchedPstmtHolder {
* This will return null if no matching PreparedStatement is found.
*/
public PreparedStatement getStmt(String stmtKey, BatchPostExecute postExecute) {
BatchedPstmt batchedPstmt = getBatchedPstmt(stmtKey, postExecute);
return (batchedPstmt == null) ? null : batchedPstmt.getStatement();
}
/**
* Return the BatchedPstmt that holds the batched statement.
*/
public BatchedPstmt getBatchedPstmt(String stmtKey, BatchPostExecute postExecute) {
BatchedPstmt bs = stmtMap.get(stmtKey);
if (bs == null) {
// the PreparedStatement has need been created
@@ -53,7 +62,7 @@ public class BatchedPstmtHolder {
if (bsSize > maxSize) {
maxSize = bsSize;
}
return bs.getStatement();
return bs;
}
/**
@@ -46,6 +46,8 @@ public abstract class DmlHandler implements PersistHandler, BindableRequest {
*/
protected DataBind dataBind;
protected BatchedPstmt batchedPstmt;
protected String sql;
/**
@@ -273,20 +275,18 @@ public abstract class DmlHandler implements PersistHandler, BindableRequest {
/**
* Return a prepared statement taking into account batch requirements.
*/
protected PreparedStatement getPstmt(SpiTransaction t, String sql, PersistRequestBean<?> request,
boolean genKeys) throws SQLException {
protected PreparedStatement getPstmt(SpiTransaction t, String sql, PersistRequestBean<?> request, boolean genKeys) throws SQLException {
BatchedPstmtHolder batch = t.getBatchControl().getPstmtHolder();
PreparedStatement stmt = batch.getStmt(sql, request);
if (stmt != null) {
return stmt;
batchedPstmt = batch.getBatchedPstmt(sql, request);
if (batchedPstmt != null) {
return batchedPstmt.getStatement();
}
stmt = getPstmt(t, sql, genKeys);
PreparedStatement stmt = getPstmt(t, sql, genKeys);
BatchedPstmt bs = new BatchedPstmt(stmt, genKeys, sql, t);
batch.addStmt(bs, request);
batchedPstmt = new BatchedPstmt(stmt, genKeys, sql, t);
batch.addStmt(batchedPstmt, request);
return stmt;
}
@@ -91,7 +91,9 @@ public class InsertHandler extends DmlHandler {
}
dataBind = bind(pstmt);
meta.bind(this, bean, withId, persistRequest.isPublish());
if (persistRequest.isBatched()) {
batchedPstmt.registerInputStreams(dataBind.getInputStreams());
}
logSql(sql);
}
@@ -47,7 +47,9 @@ public class UpdateHandler extends DmlHandler {
}
dataBind = bind(pstmt);
meta.bind(persistRequest, this, updatePlan);
if (persistRequest.isBatched()) {
batchedPstmt.registerInputStreams(dataBind.getInputStreams());
}
setUpdateGenValues();
logSql(sql);
@@ -1,8 +1,11 @@
package io.ebeaninternal.server.type;
import io.ebeaninternal.server.core.timezone.DataTimeZone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
@@ -13,10 +16,14 @@ import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class DataBind {
private static final Logger log = LoggerFactory.getLogger(DataBind.class);
private final DataTimeZone dataTimeZone;
private final PreparedStatement pstmt;
@@ -25,6 +32,8 @@ public class DataBind {
private final StringBuilder bindLog = new StringBuilder();
private List<InputStream> inputStreams;
private int pos;
public DataBind(DataTimeZone dataTimeZone, PreparedStatement pstmt, Connection connection) {
@@ -79,7 +88,24 @@ public class DataBind {
}
public int executeUpdate() throws SQLException {
return pstmt.executeUpdate();
try {
return pstmt.executeUpdate();
} finally {
closeInputStreams();
}
}
private void closeInputStreams() {
if (inputStreams != null) {
for (InputStream inputStream : inputStreams) {
try {
inputStream.close();
} catch (IOException e) {
log.warn("Error closing InputStream that was bound to PreparedStatement", e);
}
}
inputStreams = null;
}
}
public PreparedStatement getPstmt() {
@@ -147,7 +173,19 @@ public class DataBind {
pstmt.setString(++pos, String.valueOf(v));
}
/**
* Return any inputStreams that have been bound (and should be closed).
* This is used for batched statement execution only.
*/
public List<InputStream> getInputStreams() {
return inputStreams;
}
public void setBinaryStream(InputStream inputStream, long length) throws SQLException {
if (inputStreams == null) {
inputStreams = new ArrayList<>();
}
inputStreams.add(inputStream);
pstmt.setBinaryStream(++pos, inputStream, length);
}