diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/executor/StatementExecutor.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/executor/StatementExecutor.java index 0eee8894e575b33d4c280e56c3cde14127c3b5c1..5024d4b0d0321babe3ee5654de2e5c3028790fbe 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/executor/StatementExecutor.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/executor/StatementExecutor.java @@ -22,17 +22,17 @@ import com.dangdang.ddframe.rdb.sharding.constant.SQLType; import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEvent; import com.dangdang.ddframe.rdb.sharding.executor.event.DQLExecutionEvent; import com.dangdang.ddframe.rdb.sharding.executor.event.ExecutionEvent; -import com.dangdang.ddframe.rdb.sharding.executor.wrapper.StatementExecutorWrapper; import com.dangdang.ddframe.rdb.sharding.metrics.MetricsContext; +import com.dangdang.ddframe.rdb.sharding.routing.SQLExecutionUnit; import lombok.RequiredArgsConstructor; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Map.Entry; /** * 多线程执行静态语句对象请求的执行器. @@ -48,7 +48,7 @@ public final class StatementExecutor { private final SQLType sqlType; - private final Collection statementExecutorWrappers; + private final Map statements; private final EventPostman eventPostman = new EventPostman(); @@ -63,15 +63,16 @@ public final class StatementExecutor { final Map dataMap = ExecutorDataMap.getDataMap(); List result; try { - if (1 == statementExecutorWrappers.size()) { - return Collections.singletonList(executeQueryInternal(statementExecutorWrappers.iterator().next(), isExceptionThrown, dataMap)); + if (1 == statements.size()) { + Entry entry = statements.entrySet().iterator().next(); + return Collections.singletonList(executeQueryInternal(entry.getKey(), entry.getValue(), isExceptionThrown, dataMap)); } - result = executorEngine.execute(statementExecutorWrappers, new ExecuteUnit() { + result = executorEngine.execute(statements.entrySet(), new ExecuteUnit, ResultSet>() { @Override - public ResultSet execute(final StatementExecutorWrapper input) throws Exception { - synchronized (input.getStatement().getConnection()) { - return executeQueryInternal(input, isExceptionThrown, dataMap); + public ResultSet execute(final Entry input) throws Exception { + synchronized (input.getValue().getConnection()) { + return executeQueryInternal(input.getKey(), input.getValue(), isExceptionThrown, dataMap); } } }); @@ -81,14 +82,14 @@ public final class StatementExecutor { return result; } - private ResultSet executeQueryInternal(final StatementExecutorWrapper statementExecutorWrapper, final boolean isExceptionThrown, final Map dataMap) { + private ResultSet executeQueryInternal(final SQLExecutionUnit sqlExecutionUnit, final Statement statement, final boolean isExceptionThrown, final Map dataMap) { ResultSet result; ExecutorExceptionHandler.setExceptionThrown(isExceptionThrown); ExecutorDataMap.setDataMap(dataMap); - ExecutionEvent event = getExecutionEvent(statementExecutorWrapper); + ExecutionEvent event = getExecutionEvent(sqlExecutionUnit); eventPostman.post(event); try { - result = statementExecutorWrapper.getStatement().executeQuery(statementExecutorWrapper.getSqlExecutionUnit().getSql()); + result = statement.executeQuery(sqlExecutionUnit.getSql()); } catch (final SQLException ex) { eventPostman.postForExecuteFailure(event, ex); ExecutorExceptionHandler.handleException(ex); @@ -148,15 +149,16 @@ public final class StatementExecutor { final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown(); final Map dataMap = ExecutorDataMap.getDataMap(); try { - if (1 == statementExecutorWrappers.size()) { - return executeUpdateInternal(updater, statementExecutorWrappers.iterator().next(), isExceptionThrown, dataMap); + if (1 == statements.size()) { + Entry entry = statements.entrySet().iterator().next(); + return executeUpdateInternal(updater, entry.getKey(), entry.getValue(), isExceptionThrown, dataMap); } - return executorEngine.execute(statementExecutorWrappers, new ExecuteUnit() { + return executorEngine.execute(statements.entrySet(), new ExecuteUnit, Integer>() { @Override - public Integer execute(final StatementExecutorWrapper input) throws Exception { - synchronized (input.getStatement().getConnection()) { - return executeUpdateInternal(updater, input, isExceptionThrown, dataMap); + public Integer execute(final Entry input) throws Exception { + synchronized (input.getValue().getConnection()) { + return executeUpdateInternal(updater, input.getKey(), input.getValue(), isExceptionThrown, dataMap); } } }, new MergeUnit() { @@ -178,14 +180,14 @@ public final class StatementExecutor { } } - private int executeUpdateInternal(final Updater updater, final StatementExecutorWrapper statementExecutorWrapper, final boolean isExceptionThrown, final Map dataMap) { + private int executeUpdateInternal(final Updater updater, final SQLExecutionUnit sqlExecutionUnit, final Statement statement, final boolean isExceptionThrown, final Map dataMap) { int result; ExecutorExceptionHandler.setExceptionThrown(isExceptionThrown); ExecutorDataMap.setDataMap(dataMap); - ExecutionEvent event = getExecutionEvent(statementExecutorWrapper); + ExecutionEvent event = getExecutionEvent(sqlExecutionUnit); eventPostman.post(event); try { - result = updater.executeUpdate(statementExecutorWrapper.getStatement(), statementExecutorWrapper.getSqlExecutionUnit().getSql()); + result = updater.executeUpdate(statement, sqlExecutionUnit.getSql()); } catch (final SQLException ex) { eventPostman.postForExecuteFailure(event, ex); ExecutorExceptionHandler.handleException(ex); @@ -245,15 +247,16 @@ public final class StatementExecutor { final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown(); final Map dataMap = ExecutorDataMap.getDataMap(); try { - if (1 == statementExecutorWrappers.size()) { - return executeInternal(executor, statementExecutorWrappers.iterator().next(), isExceptionThrown, dataMap); + if (1 == statements.size()) { + Entry entry = statements.entrySet().iterator().next(); + return executeInternal(executor, entry.getKey(), entry.getValue(), isExceptionThrown, dataMap); } - List result = executorEngine.execute(statementExecutorWrappers, new ExecuteUnit() { + List result = executorEngine.execute(statements.entrySet(), new ExecuteUnit, Boolean>() { @Override - public Boolean execute(final StatementExecutorWrapper input) throws Exception { - synchronized (input.getStatement().getConnection()) { - return executeInternal(executor, input, isExceptionThrown, dataMap); + public Boolean execute(final Entry input) throws Exception { + synchronized (input.getValue().getConnection()) { + return executeInternal(executor, input.getKey(), input.getValue(), isExceptionThrown, dataMap); } } }); @@ -263,14 +266,14 @@ public final class StatementExecutor { } } - private boolean executeInternal(final Executor executor, final StatementExecutorWrapper statementExecutorWrapper, final boolean isExceptionThrown, final Map dataMap) { + private boolean executeInternal(final Executor executor, final SQLExecutionUnit sqlExecutionUnit, final Statement statement, final boolean isExceptionThrown, final Map dataMap) { boolean result; ExecutorExceptionHandler.setExceptionThrown(isExceptionThrown); ExecutorDataMap.setDataMap(dataMap); - ExecutionEvent event = getExecutionEvent(statementExecutorWrapper); + ExecutionEvent event = getExecutionEvent(sqlExecutionUnit); eventPostman.post(event); try { - result = executor.execute(statementExecutorWrapper.getStatement(), statementExecutorWrapper.getSqlExecutionUnit().getSql()); + result = executor.execute(statement, sqlExecutionUnit.getSql()); } catch (final SQLException ex) { eventPostman.postForExecuteFailure(event, ex); ExecutorExceptionHandler.handleException(ex); @@ -280,12 +283,12 @@ public final class StatementExecutor { return result; } - private ExecutionEvent getExecutionEvent(final StatementExecutorWrapper statementExecutorWrapper) { + private ExecutionEvent getExecutionEvent(final SQLExecutionUnit sqlExecutionUnit) { ExecutionEvent event; if (SQLType.SELECT == sqlType) { - event = new DQLExecutionEvent(statementExecutorWrapper.getSqlExecutionUnit().getDataSource(), statementExecutorWrapper.getSqlExecutionUnit().getSql()); + event = new DQLExecutionEvent(sqlExecutionUnit.getDataSource(), sqlExecutionUnit.getSql()); } else { - event = new DMLExecutionEvent(statementExecutorWrapper.getSqlExecutionUnit().getDataSource(), statementExecutorWrapper.getSqlExecutionUnit().getSql()); + event = new DMLExecutionEvent(sqlExecutionUnit.getDataSource(), sqlExecutionUnit.getSql()); } return event; } diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/core/statement/ShardingStatement.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/core/statement/ShardingStatement.java index e704922571ce156fc13bf8235a05d6a6a9f54afd..3daaf94da425d743596bf175233084c7ae23efed 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/core/statement/ShardingStatement.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/core/statement/ShardingStatement.java @@ -18,7 +18,6 @@ package com.dangdang.ddframe.rdb.sharding.jdbc.core.statement; import com.dangdang.ddframe.rdb.sharding.executor.StatementExecutor; -import com.dangdang.ddframe.rdb.sharding.executor.wrapper.StatementExecutorWrapper; import com.dangdang.ddframe.rdb.sharding.jdbc.adapter.AbstractStatementAdapter; import com.dangdang.ddframe.rdb.sharding.jdbc.core.connection.ShardingConnection; import com.dangdang.ddframe.rdb.sharding.jdbc.core.resultset.GeneratedKeysResultSet; @@ -39,8 +38,10 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; /** * 支持分片的静态语句对象. @@ -198,15 +199,15 @@ public class ShardingStatement extends AbstractStatementAdapter { private StatementExecutor generateExecutor(final String sql) throws SQLException { clearPrevious(); routeResult = new StatementRoutingEngine(shardingConnection.getShardingContext()).route(sql); - Collection statementExecutorWrappers = new LinkedList<>(); + Map statements = new HashMap<>(routeResult.getExecutionUnits().size(), 1); for (SQLExecutionUnit each : routeResult.getExecutionUnits()) { Statement statement = shardingConnection.getConnection( each.getDataSource(), routeResult.getSqlStatement().getType()).createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); replayMethodsInvocation(statement); - statementExecutorWrappers.add(new StatementExecutorWrapper(statement, each)); + statements.put(each, statement); routedStatements.add(statement); } - return new StatementExecutor(shardingConnection.getShardingContext().getExecutorEngine(), routeResult.getSqlStatement().getType(), statementExecutorWrappers); + return new StatementExecutor(shardingConnection.getShardingContext().getExecutorEngine(), routeResult.getSqlStatement().getType(), statements); } private void clearPrevious() throws SQLException { diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/core/statement/prepared/ShardingPreparedStatement.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/core/statement/prepared/ShardingPreparedStatement.java index 52190894df04d44f201ee9f7766a6c4f148c3c5b..796e71cb40dfbbcf5fbb6fae98dfc3c330607c83 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/core/statement/prepared/ShardingPreparedStatement.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/core/statement/prepared/ShardingPreparedStatement.java @@ -195,6 +195,7 @@ public final class ShardingPreparedStatement extends AbstractPreparedStatementAd private PreparedStatementExecutorWrapper wrap(final PreparedStatement preparedStatement, final SQLExecutionUnit sqlExecutionUnit) { Optional wrapperOptional = Iterators.tryFind(cachedPreparedStatementWrappers.iterator(), new Predicate() { + @Override public boolean apply(final PreparedStatementExecutorWrapper input) { return Objects.equals(input.getPreparedStatement(), preparedStatement); diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/executor/StatementExecutorTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/executor/StatementExecutorTest.java index 46c83a540fa15e7f06a3b859ca659378e42597b7..2a2e42550ec1314ec5f7834223894c50715486e0 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/executor/StatementExecutorTest.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/executor/StatementExecutorTest.java @@ -19,7 +19,6 @@ package com.dangdang.ddframe.rdb.sharding.executor; import com.dangdang.ddframe.rdb.sharding.constant.SQLType; import com.dangdang.ddframe.rdb.sharding.executor.event.EventExecutionType; -import com.dangdang.ddframe.rdb.sharding.executor.wrapper.StatementExecutorWrapper; import com.dangdang.ddframe.rdb.sharding.rewrite.SQLBuilder; import com.dangdang.ddframe.rdb.sharding.routing.SQLExecutionUnit; import org.junit.Test; @@ -30,7 +29,9 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsCollectionContaining.hasItem; @@ -50,7 +51,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { @Test public void assertNoStatement() throws SQLException { - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, Collections.emptyList()); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, Collections.emptyMap()); assertFalse(actual.execute()); assertThat(actual.executeUpdate(), is(0)); assertThat(actual.executeQuery().size(), is(0)); @@ -61,7 +62,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { Statement statement = mock(Statement.class); ResultSet resultSet = mock(ResultSet.class); when(statement.executeQuery(SELECT_FROM_DUAL)).thenReturn(resultSet); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, Collections.singletonList(createStatementExecutorWrapperForDQL(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, createStatementMap(SELECT_FROM_DUAL, statement, "ds_0")); assertThat(actual.executeQuery(), is(Collections.singletonList(resultSet))); verify(statement).executeQuery(SELECT_FROM_DUAL); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -82,8 +83,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { when(statement1.getConnection()).thenReturn(mock(Connection.class)); when(statement2.executeQuery(SELECT_FROM_DUAL)).thenReturn(resultSet2); when(statement2.getConnection()).thenReturn(mock(Connection.class)); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, - Arrays.asList(createStatementExecutorWrapperForDQL(statement1, "ds_0"), createStatementExecutorWrapperForDQL(statement2, "ds_1"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, createStatementMap(SELECT_FROM_DUAL, statement1, "ds_0", statement2, "ds_1")); List actualResultSets = actual.executeQuery(); assertThat(actualResultSets, hasItem(resultSet1)); assertThat(actualResultSets, hasItem(resultSet2)); @@ -105,7 +105,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { Statement statement = mock(Statement.class); SQLException exp = new SQLException(); when(statement.executeQuery(SELECT_FROM_DUAL)).thenThrow(exp); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, Collections.singletonList(createStatementExecutorWrapperForDQL(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, createStatementMap(SELECT_FROM_DUAL, statement, "ds_0")); assertThat(actual.executeQuery(), is(Collections.singletonList((ResultSet) null))); verify(statement).executeQuery(SELECT_FROM_DUAL); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -125,8 +125,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { when(statement2.executeQuery(SELECT_FROM_DUAL)).thenThrow(exp); when(statement1.getConnection()).thenReturn(mock(Connection.class)); when(statement2.getConnection()).thenReturn(mock(Connection.class)); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, - Arrays.asList(createStatementExecutorWrapperForDQL(statement1, "ds_0"), createStatementExecutorWrapperForDQL(statement2, "ds_1"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, createStatementMap(SELECT_FROM_DUAL, statement1, "ds_0", statement2, "ds_1")); List actualResultSets = actual.executeQuery(); assertThat(actualResultSets, is(Arrays.asList((ResultSet) null, null))); verify(statement1).executeQuery(SELECT_FROM_DUAL); @@ -146,7 +145,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { public void assertExecuteUpdateForSingleStatementSuccess() throws SQLException { Statement statement = mock(Statement.class); when(statement.executeUpdate(DELETE_FROM_DUAL)).thenReturn(10); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, Collections.singletonList(createStatementExecutorWrapperForDML(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement, "ds_0")); assertThat(actual.executeUpdate(), is(10)); verify(statement).executeUpdate(DELETE_FROM_DUAL); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -165,8 +164,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { when(statement2.executeUpdate(DELETE_FROM_DUAL)).thenReturn(20); when(statement1.getConnection()).thenReturn(mock(Connection.class)); when(statement2.getConnection()).thenReturn(mock(Connection.class)); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, - Arrays.asList(createStatementExecutorWrapperForDML(statement1, "ds_0"), createStatementExecutorWrapperForDML(statement2, "ds_1"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement1, "ds_0", statement2, "ds_1")); assertThat(actual.executeUpdate(), is(30)); verify(statement1).executeUpdate(DELETE_FROM_DUAL); verify(statement2).executeUpdate(DELETE_FROM_DUAL); @@ -186,7 +184,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { Statement statement = mock(Statement.class); SQLException exp = new SQLException(); when(statement.executeUpdate(DELETE_FROM_DUAL)).thenThrow(exp); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, Collections.singletonList(createStatementExecutorWrapperForDML(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement, "ds_0")); assertThat(actual.executeUpdate(), is(0)); verify(statement).executeUpdate(DELETE_FROM_DUAL); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -206,8 +204,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { when(statement2.executeUpdate(DELETE_FROM_DUAL)).thenThrow(exp); when(statement1.getConnection()).thenReturn(mock(Connection.class)); when(statement2.getConnection()).thenReturn(mock(Connection.class)); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, - Arrays.asList(createStatementExecutorWrapperForDML(statement1, "ds_0"), createStatementExecutorWrapperForDML(statement2, "ds_1"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement1, "ds_0", statement2, "ds_1")); assertThat(actual.executeUpdate(), is(0)); verify(statement1).executeUpdate(DELETE_FROM_DUAL); verify(statement2).executeUpdate(DELETE_FROM_DUAL); @@ -226,7 +223,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { public void assertExecuteUpdateWithAutoGeneratedKeys() throws SQLException { Statement statement = mock(Statement.class); when(statement.executeUpdate(DELETE_FROM_DUAL, Statement.NO_GENERATED_KEYS)).thenReturn(10); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, Collections.singletonList(createStatementExecutorWrapperForDML(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement, "ds_0")); assertThat(actual.executeUpdate(Statement.NO_GENERATED_KEYS), is(10)); verify(statement).executeUpdate(DELETE_FROM_DUAL, Statement.NO_GENERATED_KEYS); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -241,7 +238,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { public void assertExecuteUpdateWithColumnIndexes() throws SQLException { Statement statement = mock(Statement.class); when(statement.executeUpdate(DELETE_FROM_DUAL, new int[] {1})).thenReturn(10); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, Collections.singletonList(createStatementExecutorWrapperForDML(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement, "ds_0")); assertThat(actual.executeUpdate(new int[] {1}), is(10)); verify(statement).executeUpdate(DELETE_FROM_DUAL, new int[] {1}); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -256,7 +253,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { public void assertExecuteUpdateWithColumnNames() throws SQLException { Statement statement = mock(Statement.class); when(statement.executeUpdate(DELETE_FROM_DUAL, new String[] {"col"})).thenReturn(10); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, Collections.singletonList(createStatementExecutorWrapperForDML(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement, "ds_0")); assertThat(actual.executeUpdate(new String[] {"col"}), is(10)); verify(statement).executeUpdate(DELETE_FROM_DUAL, new String[] {"col"}); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -271,7 +268,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { public void assertExecuteForSingleStatementSuccessWithDML() throws SQLException { Statement statement = mock(Statement.class); when(statement.execute(DELETE_FROM_DUAL)).thenReturn(false); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, Collections.singletonList(createStatementExecutorWrapperForDML(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement, "ds_0")); assertFalse(actual.execute()); verify(statement).execute(DELETE_FROM_DUAL); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -290,8 +287,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { when(statement2.execute(DELETE_FROM_DUAL)).thenReturn(false); when(statement1.getConnection()).thenReturn(mock(Connection.class)); when(statement2.getConnection()).thenReturn(mock(Connection.class)); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, - Arrays.asList(createStatementExecutorWrapperForDML(statement1, "ds_0"), createStatementExecutorWrapperForDML(statement2, "ds_1"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement1, "ds_0", statement2, "ds_1")); assertFalse(actual.execute()); verify(statement1).execute(DELETE_FROM_DUAL); verify(statement2).execute(DELETE_FROM_DUAL); @@ -311,7 +307,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { Statement statement = mock(Statement.class); SQLException exp = new SQLException(); when(statement.execute(DELETE_FROM_DUAL)).thenThrow(exp); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, Collections.singletonList(createStatementExecutorWrapperForDML(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement, "ds_0")); assertFalse(actual.execute()); verify(statement).execute(DELETE_FROM_DUAL); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -331,8 +327,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { when(statement2.execute(DELETE_FROM_DUAL)).thenThrow(exp); when(statement1.getConnection()).thenReturn(mock(Connection.class)); when(statement2.getConnection()).thenReturn(mock(Connection.class)); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, - Arrays.asList(createStatementExecutorWrapperForDML(statement1, "ds_0"), createStatementExecutorWrapperForDML(statement2, "ds_1"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement1, "ds_0", statement2, "ds_1")); assertFalse(actual.execute()); verify(statement1).execute(DELETE_FROM_DUAL); verify(statement2).execute(DELETE_FROM_DUAL); @@ -351,7 +346,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { public void assertExecuteForSingleStatementWithDQL() throws SQLException { Statement statement = mock(Statement.class); when(statement.execute(SELECT_FROM_DUAL)).thenReturn(true); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, Collections.singletonList(createStatementExecutorWrapperForDQL(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, createStatementMap(SELECT_FROM_DUAL, statement, "ds_0")); assertTrue(actual.execute()); verify(statement).execute(SELECT_FROM_DUAL); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -370,14 +365,14 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { when(statement2.execute(SELECT_FROM_DUAL)).thenReturn(true); when(statement1.getConnection()).thenReturn(mock(Connection.class)); when(statement2.getConnection()).thenReturn(mock(Connection.class)); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, - Arrays.asList(createStatementExecutorWrapperForDQL(statement1, "ds_0"), createStatementExecutorWrapperForDQL(statement2, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.SELECT, createStatementMap(SELECT_FROM_DUAL, statement1, "ds_0", statement2, "ds_1")); assertTrue(actual.execute()); verify(statement1).execute(SELECT_FROM_DUAL); verify(statement2).execute(SELECT_FROM_DUAL); verify(statement1).getConnection(); verify(statement2).getConnection(); - verify(getEventCaller(), times(4)).verifyDataSource("ds_0"); + verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); + verify(getEventCaller(), times(2)).verifyDataSource("ds_1"); verify(getEventCaller(), times(4)).verifySQL(SELECT_FROM_DUAL); verify(getEventCaller(), times(4)).verifyParameters(Collections.emptyList()); verify(getEventCaller(), times(2)).verifyEventExecutionType(EventExecutionType.BEFORE_EXECUTE); @@ -389,7 +384,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { public void assertExecuteWithAutoGeneratedKeys() throws SQLException { Statement statement = mock(Statement.class); when(statement.execute(DELETE_FROM_DUAL, Statement.NO_GENERATED_KEYS)).thenReturn(false); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, Collections.singletonList(createStatementExecutorWrapperForDML(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement, "ds_0")); assertFalse(actual.execute(Statement.NO_GENERATED_KEYS)); verify(statement).execute(DELETE_FROM_DUAL, Statement.NO_GENERATED_KEYS); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -404,7 +399,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { public void assertExecuteWithColumnIndexes() throws SQLException { Statement statement = mock(Statement.class); when(statement.execute(DELETE_FROM_DUAL, new int[] {1})).thenReturn(false); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, Collections.singletonList(createStatementExecutorWrapperForDML(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement, "ds_0")); assertFalse(actual.execute(new int[] {1})); verify(statement).execute(DELETE_FROM_DUAL, new int[] {1}); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -419,7 +414,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { public void assertExecuteWithColumnNames() throws SQLException { Statement statement = mock(Statement.class); when(statement.execute(DELETE_FROM_DUAL, new String[] {"col"})).thenReturn(false); - StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, Collections.singletonList(createStatementExecutorWrapperForDML(statement, "ds_0"))); + StatementExecutor actual = new StatementExecutor(getExecutorEngine(), SQLType.DELETE, createStatementMap(DELETE_FROM_DUAL, statement, "ds_0")); assertFalse(actual.execute(new String[] {"col"})); verify(statement).execute(DELETE_FROM_DUAL, new String[] {"col"}); verify(getEventCaller(), times(2)).verifyDataSource("ds_0"); @@ -430,15 +425,18 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest { verify(getEventCaller(), times(0)).verifyException(null); } - private StatementExecutorWrapper createStatementExecutorWrapperForDQL(final Statement statement, final String dataSource) { + private Map createStatementMap(final String sql, final Statement statement, final String dataSource) { + Map result = new HashMap<>(); SQLBuilder sqlBuilder = new SQLBuilder(); - sqlBuilder.appendLiterals(SELECT_FROM_DUAL); - return new StatementExecutorWrapper(statement, new SQLExecutionUnit(dataSource, sqlBuilder.toSQL(Collections.emptyMap()))); + sqlBuilder.appendLiterals(sql); + result.put(new SQLExecutionUnit(dataSource, sqlBuilder.toSQL(Collections.emptyMap())), statement); + return result; } - private StatementExecutorWrapper createStatementExecutorWrapperForDML(final Statement statement, final String dataSource) { - SQLBuilder sqlBuilder = new SQLBuilder(); - sqlBuilder.appendLiterals(DELETE_FROM_DUAL); - return new StatementExecutorWrapper(statement, new SQLExecutionUnit(dataSource, sqlBuilder.toSQL(Collections.emptyMap()))); + private Map createStatementMap(final String sql, final Statement statement1, final String dataSource1, final Statement statement2, final String dataSource2) { + Map result = new HashMap<>(); + result.putAll(createStatementMap(sql, statement1, dataSource1)); + result.putAll(createStatementMap(sql, statement2, dataSource2)); + return result; } }