Property changes on: D:\Programs\iBatis\trunk ___________________________________________________________________ Name: svn:ignore + srcs bin jars .check* .classpath .project build.xml Index: D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/dao/client/template/SqlMapDaoTemplate.java =================================================================== --- D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/dao/client/template/SqlMapDaoTemplate.java (revision 233455) +++ D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/dao/client/template/SqlMapDaoTemplate.java (working copy) @@ -344,4 +344,14 @@ } } + /** + * Executes (flushes) all statements currently batched. + */ + public int[] executeBatchDetailed() { + try { + return getSqlMapExecutor().executeBatchDetailed(); + } catch (SQLException e) { + throw new DaoException("Failed to executeBatch. Cause: " + e, e); + } + } } Index: D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapSessionImpl.java =================================================================== --- D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapSessionImpl.java (revision 233455) +++ D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapSessionImpl.java (working copy) @@ -15,6 +15,7 @@ */ package com.ibatis.sqlmap.engine.impl; +import com.ibatis.common.jdbc.exception.MoreBatchUpdateException; import com.ibatis.common.jdbc.exception.NestedSQLException; import com.ibatis.common.util.PaginatedList; import com.ibatis.sqlmap.client.SqlMapSession; @@ -26,6 +27,8 @@ import com.ibatis.sqlmap.engine.transaction.TransactionException; import javax.sql.DataSource; + +import java.sql.BatchUpdateException; import java.sql.Connection; import java.sql.SQLException; import java.util.List; @@ -145,6 +148,11 @@ return delegate.executeBatch(session); } + public int[] executeBatchDetailed() throws MoreBatchUpdateException, + BatchUpdateException, SQLException { + return delegate.executeBatchDetailed(session); + } + public void setUserConnection(Connection connection) throws SQLException { delegate.setUserProvidedTransaction(session, connection); } Index: D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapExecutorDelegate.java =================================================================== --- D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapExecutorDelegate.java (revision 233455) +++ D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapExecutorDelegate.java (working copy) @@ -17,6 +17,7 @@ import com.ibatis.common.beans.Probe; import com.ibatis.common.beans.ProbeFactory; +import com.ibatis.common.jdbc.exception.MoreBatchUpdateException; import com.ibatis.common.jdbc.exception.NestedSQLException; import com.ibatis.common.util.PaginatedList; import com.ibatis.common.util.ThrottledPool; @@ -42,6 +43,8 @@ import com.ibatis.sqlmap.engine.type.TypeHandlerFactory; import javax.sql.DataSource; + +import java.sql.BatchUpdateException; import java.sql.Connection; import java.sql.SQLException; import java.util.HashMap; @@ -800,6 +803,27 @@ session.setInBatch(false); return sqlExecutor.executeBatch(session); } + + /** + * Executes (flushes) all statements currently batched. The signature of this + * method is the best we can offer as the JDBC specification allows different + * behaviors that cannot be cleanly abstracted. + * + * @param session Is the session scope. + * @return Returns the int array which is returned by method + * executeBatch of class java.sql.Statement, + * which contains update counts for every batch. + * @throws MoreBatchUpdateException If there was minimum one batch which + * failed. Some more batches were tried to be executed. + * @throws BatchUpdateException If there was minimum one batch which + * failed. Only batches until the failed one were executed. + * @throws SQLException If a general failure occurred. + */ + public int[] executeBatchDetailed(SessionScope session) + throws MoreBatchUpdateException, BatchUpdateException, SQLException { + session.setInBatch(false); + return sqlExecutor.executeBatchDetailed(session); + } /** * Use a user-provided transaction for a session Index: D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapClientImpl.java =================================================================== --- D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapClientImpl.java (revision 233455) +++ D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapClientImpl.java (working copy) @@ -16,6 +16,7 @@ package com.ibatis.sqlmap.engine.impl; import com.ibatis.common.util.PaginatedList; +import com.ibatis.common.jdbc.exception.MoreBatchUpdateException; import com.ibatis.common.logging.Log; import com.ibatis.common.logging.LogFactory; import com.ibatis.sqlmap.client.SqlMapException; @@ -26,6 +27,7 @@ import com.ibatis.sqlmap.engine.binding.MapperProxy; import javax.sql.DataSource; +import java.sql.BatchUpdateException; import java.sql.Connection; import java.sql.SQLException; import java.util.List; @@ -126,6 +128,11 @@ return getLocalSqlMapSession().executeBatch(); } + public int[] executeBatchDetailed() throws MoreBatchUpdateException, + BatchUpdateException, SQLException { + return getLocalSqlMapSession().executeBatchDetailed(); + } + public void setUserConnection(Connection connection) throws SQLException { getLocalSqlMapSession().setUserConnection(connection); } Index: D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/engine/execution/SqlExecutor.java =================================================================== --- D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/engine/execution/SqlExecutor.java (revision 233455) +++ D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/engine/execution/SqlExecutor.java (working copy) @@ -15,6 +15,7 @@ */ package com.ibatis.sqlmap.engine.execution; +import com.ibatis.common.jdbc.exception.MoreBatchUpdateException; import com.ibatis.sqlmap.engine.mapping.parameter.BasicParameterMapping; import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap; import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMapping; @@ -26,6 +27,8 @@ import java.sql.*; import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; import java.util.List; /** @@ -135,6 +138,34 @@ } /** + * Execute a batch of statements. + * + * @param session Is the session scope. + * @return Returns the int array which is returned by method + * executeBatch of class java.sql.Statement, + * which contains update counts for every batch. + * @throws MoreBatchUpdateException If there was minimum one batch which + * failed. All batches were tried to be executed. + * @throws BatchUpdateException If there was minimum one batch which + * failed. Only batches until the failed one were executed. + * @throws SQLException If a general failure occurred. + */ + public int[] executeBatchDetailed(SessionScope session) + throws MoreBatchUpdateException, BatchUpdateException, SQLException { + int[] rows = null; + Batch batch = (Batch) session.getBatch(); + if (batch != null) { + try { + rows = batch.executeBatchDetailed(); + } finally { + batch.cleanupBatch(); + } + } + return rows; + } + + + /** * Long form of the method to execute a query * * @param request - the request scope @@ -466,8 +497,9 @@ */ public int executeBatch() throws SQLException { int totalRowCount = 0; - for (int i = 0, n = statementList.size(); i < n; i++) { - PreparedStatement ps = (PreparedStatement) statementList.get(i); + Iterator it = statementList.iterator(); + while (it.hasNext()) { + PreparedStatement ps = (PreparedStatement) it.next(); int[] rowCounts = ps.executeBatch(); for (int j = 0; j < rowCounts.length; j++) { if (rowCounts[j] == SUCCESS_NO_INFO) { @@ -483,11 +515,96 @@ } /** + * Execute the current session's batch. + * + * @return Returns the int array which is returned by method + * executeBatch of class + * java.sql.Statement, which contains update counts + * for every batch. + * @throws MoreBatchUpdateException + * If there was minimum one batch which failed. Some more + * batches were tried to be executed. + * @throws BatchUpdateException + * If there was minimum one batch which failed. Only batches + * until the failed one were executed. + * @throws SQLException + * If a general failure occurred. + */ + public int[] executeBatchDetailed() + throws MoreBatchUpdateException, BatchUpdateException, SQLException { + List rowCountList = new LinkedList(); + Iterator it = statementList.iterator(); + while (it.hasNext()) { + PreparedStatement ps = (PreparedStatement) it.next(); + int[] rowCounts; + boolean error = false; + try { + rowCounts = ps.executeBatch(); + } catch (BatchUpdateException e) { + rowCounts = e.getUpdateCounts(); + error = true; + } + if (rowCounts != null && rowCounts.length > 0) { + rowCountList.add(rowCounts); + } + if (error) { + int[] successfulRowCounts + = convertIntArraysInListToOneIntArray(rowCountList); + throw new BatchUpdateException( + "Executed batch statement number " + + (successfulRowCounts.length + 1) + + "failed.", successfulRowCounts); + } else { + for (int j = 0; j < rowCounts.length; j++) { + if (rowCounts[j] == EXECUTE_FAILED) { + int[] totalRowCount + = convertIntArraysInListToOneIntArray(rowCountList); + throw new MoreBatchUpdateException( + "Minimum one batch statement failed.", + totalRowCount); + } + } + } + } + return convertIntArraysInListToOneIntArray(rowCountList); + } + + /** + * Method to convert a list which conatins int arrays into one big int + * array. + * + * @param rowCountList Is a list with the given int arrays. + * @return Returns one big int array. + */ + private int[] convertIntArraysInListToOneIntArray(List rowCountList) { + int totalSize = 0; + Iterator it = rowCountList.iterator(); + while (it.hasNext()) { + int[] array = (int[]) it.next(); + totalSize += array.length; + } + + int[] rowCount = new int[totalSize]; + int pos = 0; + it = rowCountList.iterator(); + while (it.hasNext()) { + int[] array = (int[]) it.next(); + for (int i = 0; i < array.length; i++) { + rowCount[pos] = array[i]; + pos++; + } + } + + return rowCount; + } + + /** * Close all the statements in the batch and clear all the statements */ public void cleanupBatch() { - for (int i = 0, n = statementList.size(); i < n; i++) { - PreparedStatement ps = (PreparedStatement) statementList.get(i); + Iterator it = statementList.iterator(); + while (it.hasNext()) { + PreparedStatement ps = (PreparedStatement) it.next(); closeStatement(ps); } currentSql = null; Index: D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/client/SqlMapExecutor.java =================================================================== --- D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/client/SqlMapExecutor.java (revision 233455) +++ D:/Programs/iBatis/trunk/mapper/mapper2/src/com/ibatis/sqlmap/client/SqlMapExecutor.java (working copy) @@ -15,9 +15,11 @@ */ package com.ibatis.sqlmap.client; +import com.ibatis.common.jdbc.exception.MoreBatchUpdateException; import com.ibatis.common.util.PaginatedList; import com.ibatis.sqlmap.client.event.RowHandler; +import java.sql.BatchUpdateException; import java.sql.SQLException; import java.util.List; import java.util.Map; @@ -222,4 +224,20 @@ * fails. */ int executeBatch() throws SQLException; + + /** + * Executes (flushes) all statements currently batched. The signature of this + * method is the best we can offer as the JDBC specification allows different + * behaviors that cannot be cleanly abstracted. + * + * @return Returns the int array which is returned by method + * executeBatch of class java.sql.Statement, + * which contains update counts for every batch. + * @throws MoreBatchUpdateException If there was minimum one batch which + * failed. Some more batches were tried to be executed. + * @throws BatchUpdateException If there was minimum one batch which + * failed. Only batches until the failed one were executed. + * @throws SQLException If a general failure occurred. + */ + int[] executeBatchDetailed() throws MoreBatchUpdateException, BatchUpdateException, SQLException; }