diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java index 73d09d09b7..1e35195913 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java @@ -91,6 +91,7 @@ import static org.jooq.util.sqlite.SQLiteDSL.rowid; import java.sql.CallableStatement; import java.sql.Connection; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -140,6 +141,7 @@ import org.jooq.exception.DataAccessException; import org.jooq.impl.Tools.BooleanDataKey; import org.jooq.impl.Tools.DataKey; import org.jooq.tools.JooqLogger; +import org.jooq.tools.jdbc.BatchedPreparedStatement; import org.jooq.tools.jdbc.JDBCUtils; /** @@ -952,7 +954,7 @@ abstract class AbstractDMLQuery extends AbstractRowCountQuery // SQLite can select _rowid_ after the insert case SQLITE: { listener.executeStart(ctx); - result = ctx.statement().executeUpdate(); + result = executeImmediate(ctx.statement()).executeUpdate(); ctx.rows(result); listener.executeEnd(ctx); @@ -979,7 +981,7 @@ abstract class AbstractDMLQuery extends AbstractRowCountQuery case CUBRID: { listener.executeStart(ctx); - result = ctx.statement().executeUpdate(); + result = executeImmediate(ctx.statement()).executeUpdate(); ctx.rows(result); listener.executeEnd(ctx); @@ -1153,9 +1155,20 @@ abstract class AbstractDMLQuery extends AbstractRowCountQuery } } + /** + * Make sure a {@link PreparedStatement}, which may be a + * {@link BatchedPreparedStatement}, is executed immediately, not batched. + */ + private final PreparedStatement executeImmediate(PreparedStatement s) throws SQLException { + if (s.isWrapperFor(BatchedPreparedStatement.class)) + s.unwrap(BatchedPreparedStatement.class).setExecuteImmediate(true); + + return s; + } + private final ResultSet executeReturningGeneratedKeys(ExecuteContext ctx, ExecuteListener listener) throws SQLException { listener.executeStart(ctx); - int result = ctx.statement().executeUpdate(); + int result = executeImmediate(ctx.statement()).executeUpdate(); ctx.rows(result); listener.executeEnd(ctx); @@ -1166,7 +1179,7 @@ abstract class AbstractDMLQuery extends AbstractRowCountQuery ResultSet rs; listener.executeStart(ctx); - int result = ctx.statement().executeUpdate(); + int result = executeImmediate(ctx.statement()).executeUpdate(); ctx.rows(result); listener.executeEnd(ctx); diff --git a/jOOQ/src/main/java/org/jooq/tools/jdbc/BatchedConnection.java b/jOOQ/src/main/java/org/jooq/tools/jdbc/BatchedConnection.java index 6221128f75..ccccbc2055 100644 --- a/jOOQ/src/main/java/org/jooq/tools/jdbc/BatchedConnection.java +++ b/jOOQ/src/main/java/org/jooq/tools/jdbc/BatchedConnection.java @@ -93,6 +93,21 @@ public class BatchedConnection extends DefaultConnection { this.batchSize = batchSize; } + // ------------------------------------------------------------------------- + // XXX: Wrappers + // ------------------------------------------------------------------------- + + @SuppressWarnings("unchecked") + @Override + public T unwrap(Class iface) throws SQLException { + return BatchedConnection.class == iface ? (T) this : super.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return BatchedConnection.class == iface || super.isWrapperFor(iface); + } + // ------------------------------------------------------------------------- // XXX: Utilities // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/tools/jdbc/BatchedPreparedStatement.java b/jOOQ/src/main/java/org/jooq/tools/jdbc/BatchedPreparedStatement.java index e6ed4951fa..87f3396da0 100644 --- a/jOOQ/src/main/java/org/jooq/tools/jdbc/BatchedPreparedStatement.java +++ b/jOOQ/src/main/java/org/jooq/tools/jdbc/BatchedPreparedStatement.java @@ -57,6 +57,7 @@ public class BatchedPreparedStatement extends DefaultPreparedStatement { private static final JooqLogger log = JooqLogger.getLogger(BatchedPreparedStatement.class); int batches; + boolean executeImmediate; public BatchedPreparedStatement(BatchedConnection connection, PreparedStatement delegate) { super(delegate, connection); @@ -66,10 +67,23 @@ public class BatchedPreparedStatement extends DefaultPreparedStatement { return (BatchedConnection) super.getConnection(); } + public boolean getExecuteImmediate() { + return this.executeImmediate; + } + + public void setExecuteImmediate(boolean executeImmediate) { + this.executeImmediate = executeImmediate; + } + private void resetBatches() { batches = 0; } + private void logExecuteImmediate() throws SQLException { + if (log.isDebugEnabled()) + log.debug("BatchedStatement", "Skipped batching statement: " + getBatchedConnection().lastSQL); + } + private void logBatch() throws SQLException { if (log.isDebugEnabled()) log.debug("BatchedStatement", "Batched " + batches + " times: " + getBatchedConnection().lastSQL); @@ -82,20 +96,47 @@ public class BatchedPreparedStatement extends DefaultPreparedStatement { resetBatches(); } + // ------------------------------------------------------------------------- + // XXX: Wrappers + // ------------------------------------------------------------------------- + + @SuppressWarnings("unchecked") + @Override + public T unwrap(Class iface) throws SQLException { + return BatchedPreparedStatement.class == iface ? (T) this : super.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return BatchedPreparedStatement.class == iface || super.isWrapperFor(iface); + } + // ------------------------------------------------------------------------- // XXX: Executing queries // ------------------------------------------------------------------------- @Override public int executeUpdate() throws SQLException { - addBatch(); - return 0; + if (executeImmediate) { + logExecuteImmediate(); + return super.executeUpdate(); + } + else { + addBatch(); + return 0; + } } @Override public boolean execute() throws SQLException { - addBatch(); - return false; + if (executeImmediate) { + logExecuteImmediate(); + return super.execute(); + } + else { + addBatch(); + return false; + } } @Override