提交 905b94ac 编写于 作者: G gaohongtao 提交者: gaohongtao

fixed #166 concurrency execution error for druid ds pool

上级 9360049f
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package com.dangdang.ddframe.rdb.sharding.executor;
import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEvent;
import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEventBus;
import com.dangdang.ddframe.rdb.sharding.executor.event.DQLExecutionEvent;
import com.dangdang.ddframe.rdb.sharding.executor.event.DQLExecutionEventBus;
import com.dangdang.ddframe.rdb.sharding.executor.event.EventExecutionType;
import com.dangdang.ddframe.rdb.sharding.executor.wrapper.AbstractExecutorWrapper;
import com.dangdang.ddframe.rdb.sharding.executor.wrapper.BatchPreparedStatementExecutorWrapper;
import com.google.common.base.Optional;
import lombok.RequiredArgsConstructor;
import java.sql.SQLException;
import java.util.Collection;
/**
* 消息投递员.
* 负责SQL执行消息的投递
*
* @author gaohongtao.
*/
@RequiredArgsConstructor
class EventPostman {
private final Collection<? extends AbstractExecutorWrapper> statementExecutorWrappers;
void postExecutionEvents() {
for (AbstractExecutorWrapper each : statementExecutorWrappers) {
if (each.getDMLExecutionEvent().isPresent()) {
DMLExecutionEventBus.post(each.getDMLExecutionEvent().get());
} else if (each.getDQLExecutionEvent().isPresent()) {
DQLExecutionEventBus.post(each.getDQLExecutionEvent().get());
}
}
}
void postExecutionEventsAfterExecution(final AbstractExecutorWrapper statementExecutorWrapper) {
postExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS, Optional.<SQLException>absent());
}
void postExecutionEventsAfterExecution(final AbstractExecutorWrapper statementExecutorWrapper, final EventExecutionType eventExecutionType, final Optional<SQLException> exp) {
if (statementExecutorWrapper.getDMLExecutionEvent().isPresent()) {
DMLExecutionEvent event = statementExecutorWrapper.getDMLExecutionEvent().get();
event.setEventExecutionType(eventExecutionType);
event.setExp(exp);
DMLExecutionEventBus.post(event);
} else if (statementExecutorWrapper.getDQLExecutionEvent().isPresent()) {
DQLExecutionEvent event = statementExecutorWrapper.getDQLExecutionEvent().get();
event.setEventExecutionType(eventExecutionType);
event.setExp(exp);
DQLExecutionEventBus.post(event);
}
}
void postBatchExecutionEventsAfterExecution(final BatchPreparedStatementExecutorWrapper batchPreparedStatementExecutorWrapper) {
postBatchExecutionEventsAfterExecution(batchPreparedStatementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS, Optional.<SQLException>absent());
}
void postBatchExecutionEventsAfterExecution(
final BatchPreparedStatementExecutorWrapper batchPreparedStatementExecutorWrapper, final EventExecutionType eventExecutionType, final Optional<SQLException> exp) {
for (DMLExecutionEvent each : batchPreparedStatementExecutorWrapper.getDmlExecutionEvents()) {
each.setEventExecutionType(eventExecutionType);
each.setExp(exp);
DMLExecutionEventBus.post(each);
}
}
}
......@@ -18,16 +18,11 @@
package com.dangdang.ddframe.rdb.sharding.executor;
import com.codahale.metrics.Timer.Context;
import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEvent;
import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEventBus;
import com.dangdang.ddframe.rdb.sharding.executor.event.DQLExecutionEvent;
import com.dangdang.ddframe.rdb.sharding.executor.event.DQLExecutionEventBus;
import com.dangdang.ddframe.rdb.sharding.executor.event.EventExecutionType;
import com.dangdang.ddframe.rdb.sharding.executor.wrapper.BatchPreparedStatementExecutorWrapper;
import com.dangdang.ddframe.rdb.sharding.executor.wrapper.PreparedStatementExecutorWrapper;
import com.dangdang.ddframe.rdb.sharding.metrics.MetricsContext;
import com.google.common.base.Optional;
import lombok.RequiredArgsConstructor;
import java.sql.ResultSet;
import java.sql.SQLException;
......@@ -42,13 +37,20 @@ import java.util.Map;
* @author zhangliang
* @author caohao
*/
@RequiredArgsConstructor
public final class PreparedStatementExecutor {
private final ExecutorEngine executorEngine;
private final Collection<PreparedStatementExecutorWrapper> preparedStatementExecutorWrappers;
private final EventPostman eventPostman;
public PreparedStatementExecutor(final ExecutorEngine executorEngine, final Collection<PreparedStatementExecutorWrapper> preparedStatementExecutorWrappers) {
this.executorEngine = executorEngine;
this.preparedStatementExecutorWrappers = preparedStatementExecutorWrappers;
this.eventPostman = new EventPostman(preparedStatementExecutorWrappers);
}
/**
* 执行SQL查询.
*
......@@ -56,7 +58,7 @@ public final class PreparedStatementExecutor {
*/
public List<ResultSet> executeQuery() {
Context context = MetricsContext.start("ShardingPreparedStatement-executeQuery");
postExecutionEvents();
eventPostman.postExecutionEvents();
List<ResultSet> result;
final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
final Map<String, Object> dataMap = ExecutorDataMap.getDataMap();
......@@ -68,7 +70,9 @@ public final class PreparedStatementExecutor {
@Override
public ResultSet execute(final PreparedStatementExecutorWrapper input) throws Exception {
return executeQueryInternal(input, isExceptionThrown, dataMap);
synchronized (input.getPreparedStatement().getConnection()) {
return executeQueryInternal(input, isExceptionThrown, dataMap);
}
}
});
} finally {
......@@ -85,11 +89,11 @@ public final class PreparedStatementExecutor {
try {
result = preparedStatementExecutorWrapper.getPreparedStatement().executeQuery();
} catch (final SQLException ex) {
postExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
eventPostman.postExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
ExecutorExceptionHandler.handleException(ex);
return null;
}
postExecutionEventsAfterExecution(preparedStatementExecutorWrapper);
eventPostman.postExecutionEventsAfterExecution(preparedStatementExecutorWrapper);
return result;
}
......@@ -100,7 +104,7 @@ public final class PreparedStatementExecutor {
*/
public int executeUpdate() {
Context context = MetricsContext.start("ShardingPreparedStatement-executeUpdate");
postExecutionEvents();
eventPostman.postExecutionEvents();
final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
final Map<String, Object> dataMap = ExecutorDataMap.getDataMap();
try {
......@@ -111,7 +115,9 @@ public final class PreparedStatementExecutor {
@Override
public Integer execute(final PreparedStatementExecutorWrapper input) throws Exception {
return executeUpdateInternal(input, isExceptionThrown, dataMap);
synchronized (input.getPreparedStatement().getConnection()) {
return executeUpdateInternal(input, isExceptionThrown, dataMap);
}
}
}, new MergeUnit<Integer, Integer>() {
......@@ -140,11 +146,11 @@ public final class PreparedStatementExecutor {
try {
result = preparedStatementExecutorWrapper.getPreparedStatement().executeUpdate();
} catch (final SQLException ex) {
postExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
eventPostman.postExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
ExecutorExceptionHandler.handleException(ex);
return 0;
}
postExecutionEventsAfterExecution(preparedStatementExecutorWrapper);
eventPostman.postExecutionEventsAfterExecution(preparedStatementExecutorWrapper);
return result;
}
......@@ -155,19 +161,21 @@ public final class PreparedStatementExecutor {
*/
public boolean execute() {
Context context = MetricsContext.start("ShardingPreparedStatement-execute");
postExecutionEvents();
eventPostman.postExecutionEvents();
final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
final Map<String, Object> dataMap = ExecutorDataMap.getDataMap();
try {
if (1 == preparedStatementExecutorWrappers.size()) {
PreparedStatementExecutorWrapper preparedStatementExecutorWrapper = preparedStatementExecutorWrappers.iterator().next();
return executeInternal(preparedStatementExecutorWrapper, isExceptionThrown, dataMap, Optional.fromNullable(context));
return executeInternal(preparedStatementExecutorWrapper, isExceptionThrown, dataMap);
}
List<Boolean> result = executorEngine.execute(preparedStatementExecutorWrappers, new ExecuteUnit<PreparedStatementExecutorWrapper, Boolean>() {
@Override
public Boolean execute(final PreparedStatementExecutorWrapper input) throws Exception {
return executeInternal(input, isExceptionThrown, dataMap, Optional.<Context>absent());
synchronized (input.getPreparedStatement().getConnection()) {
return executeInternal(input, isExceptionThrown, dataMap);
}
}
});
return (null == result || result.isEmpty()) ? false : result.get(0);
......@@ -177,22 +185,18 @@ public final class PreparedStatementExecutor {
}
private boolean executeInternal(final PreparedStatementExecutorWrapper preparedStatementExecutorWrapper,
final boolean isExceptionThrown, final Map<String, Object> dataMap, final Optional<Context> context) {
final boolean isExceptionThrown, final Map<String, Object> dataMap) {
boolean result;
ExecutorExceptionHandler.setExceptionThrown(isExceptionThrown);
ExecutorDataMap.setDataMap(dataMap);
try {
result = preparedStatementExecutorWrapper.getPreparedStatement().execute();
} catch (final SQLException ex) {
postExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
eventPostman.postExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
ExecutorExceptionHandler.handleException(ex);
return false;
} finally {
if (context.isPresent()) {
MetricsContext.stop(context.get());
}
}
postExecutionEventsAfterExecution(preparedStatementExecutorWrapper);
eventPostman.postExecutionEventsAfterExecution(preparedStatementExecutorWrapper);
return result;
}
......@@ -204,7 +208,7 @@ public final class PreparedStatementExecutor {
*/
public int[] executeBatch() {
Context context = MetricsContext.start("ShardingPreparedStatement-executeUpdate");
postExecutionEvents();
eventPostman.postExecutionEvents();
final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
final Map<String, Object> dataMap = ExecutorDataMap.getDataMap();
try {
......@@ -215,7 +219,9 @@ public final class PreparedStatementExecutor {
@Override
public int[] execute(final PreparedStatementExecutorWrapper input) throws Exception {
return executeBatchInternal((BatchPreparedStatementExecutorWrapper) input, isExceptionThrown, dataMap);
synchronized (input.getPreparedStatement().getConnection()) {
return executeBatchInternal((BatchPreparedStatementExecutorWrapper) input, isExceptionThrown, dataMap);
}
}
}, new MergeUnit<int[], int[]>() {
......@@ -249,55 +255,11 @@ public final class PreparedStatementExecutor {
try {
result = batchPreparedStatementExecutorWrapper.getPreparedStatement().executeBatch();
} catch (final SQLException ex) {
postBatchExecutionEventsAfterExecution(batchPreparedStatementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
eventPostman.postBatchExecutionEventsAfterExecution(batchPreparedStatementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
ExecutorExceptionHandler.handleException(ex);
return null;
}
postBatchExecutionEventsAfterExecution(batchPreparedStatementExecutorWrapper);
eventPostman.postBatchExecutionEventsAfterExecution(batchPreparedStatementExecutorWrapper);
return result;
}
private void postBatchExecutionEventsAfterExecution(final BatchPreparedStatementExecutorWrapper batchPreparedStatementExecutorWrapper) {
postBatchExecutionEventsAfterExecution(batchPreparedStatementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS, Optional.<SQLException>absent());
}
private void postBatchExecutionEventsAfterExecution(
final BatchPreparedStatementExecutorWrapper batchPreparedStatementExecutorWrapper, final EventExecutionType eventExecutionType, final Optional<SQLException> exp) {
for (DMLExecutionEvent each : batchPreparedStatementExecutorWrapper.getDmlExecutionEvents()) {
each.setEventExecutionType(eventExecutionType);
each.setExp(exp);
DMLExecutionEventBus.post(each);
}
}
private void postExecutionEvents() {
for (PreparedStatementExecutorWrapper each : preparedStatementExecutorWrappers) {
if (each.getDMLExecutionEvent().isPresent()) {
DMLExecutionEventBus.post(each.getDMLExecutionEvent().get());
}
if (each.getDQLExecutionEvent().isPresent()) {
DQLExecutionEventBus.post(each.getDQLExecutionEvent().get());
}
}
}
private void postExecutionEventsAfterExecution(final PreparedStatementExecutorWrapper preparedStatementExecutorWrapper) {
postExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS, Optional.<SQLException>absent());
}
private void postExecutionEventsAfterExecution(final PreparedStatementExecutorWrapper preparedStatementExecutorWrapper,
final EventExecutionType eventExecutionType, final Optional<SQLException> exp) {
if (preparedStatementExecutorWrapper.getDMLExecutionEvent().isPresent()) {
DMLExecutionEvent event = preparedStatementExecutorWrapper.getDMLExecutionEvent().get();
event.setEventExecutionType(eventExecutionType);
event.setExp(exp);
DMLExecutionEventBus.post(event);
}
if (preparedStatementExecutorWrapper.getDQLExecutionEvent().isPresent()) {
DQLExecutionEvent event = preparedStatementExecutorWrapper.getDQLExecutionEvent().get();
event.setEventExecutionType(eventExecutionType);
event.setExp(exp);
DQLExecutionEventBus.post(event);
}
}
}
......@@ -18,10 +18,6 @@
package com.dangdang.ddframe.rdb.sharding.executor;
import com.codahale.metrics.Timer.Context;
import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEvent;
import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEventBus;
import com.dangdang.ddframe.rdb.sharding.executor.event.DQLExecutionEvent;
import com.dangdang.ddframe.rdb.sharding.executor.event.DQLExecutionEventBus;
import com.dangdang.ddframe.rdb.sharding.executor.event.EventExecutionType;
import com.dangdang.ddframe.rdb.sharding.executor.wrapper.StatementExecutorWrapper;
import com.dangdang.ddframe.rdb.sharding.metrics.MetricsContext;
......@@ -50,6 +46,8 @@ public final class StatementExecutor {
private final Collection<StatementExecutorWrapper> statementExecutorWrappers = new ArrayList<>();
private final EventPostman eventPostman = new EventPostman(statementExecutorWrappers);
/**
* 添加静态语句对象至执行上下文.
*
......@@ -66,7 +64,7 @@ public final class StatementExecutor {
*/
public List<ResultSet> executeQuery() {
Context context = MetricsContext.start("ShardingStatement-executeQuery");
postExecutionEvents();
eventPostman.postExecutionEvents();
final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
final Map<String, Object> dataMap = ExecutorDataMap.getDataMap();
List<ResultSet> result;
......@@ -78,7 +76,9 @@ public final class StatementExecutor {
@Override
public ResultSet execute(final StatementExecutorWrapper input) throws Exception {
return executeQueryInternal(input, isExceptionThrown, dataMap);
synchronized (input.getStatement().getConnection()) {
return executeQueryInternal(input, isExceptionThrown, dataMap);
}
}
});
} finally {
......@@ -94,11 +94,11 @@ public final class StatementExecutor {
try {
result = statementExecutorWrapper.getStatement().executeQuery(statementExecutorWrapper.getSqlExecutionUnit().getSql());
} catch (final SQLException ex) {
postExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
eventPostman.postExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
ExecutorExceptionHandler.handleException(ex);
return null;
}
postExecutionEventsAfterExecution(statementExecutorWrapper);
eventPostman.postExecutionEventsAfterExecution(statementExecutorWrapper);
return result;
}
......@@ -149,7 +149,7 @@ public final class StatementExecutor {
private int executeUpdate(final Updater updater) {
Context context = MetricsContext.start("ShardingStatement-executeUpdate");
postExecutionEvents();
eventPostman.postExecutionEvents();
final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
final Map<String, Object> dataMap = ExecutorDataMap.getDataMap();
try {
......@@ -160,7 +160,9 @@ public final class StatementExecutor {
@Override
public Integer execute(final StatementExecutorWrapper input) throws Exception {
return executeUpdateInternal(updater, input, isExceptionThrown, dataMap);
synchronized (input.getStatement().getConnection()) {
return executeUpdateInternal(updater, input, isExceptionThrown, dataMap);
}
}
}, new MergeUnit<Integer, Integer>() {
......@@ -189,11 +191,11 @@ public final class StatementExecutor {
try {
result = updater.executeUpdate(statementExecutorWrapper.getStatement(), statementExecutorWrapper.getSqlExecutionUnit().getSql());
} catch (final SQLException ex) {
postExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
eventPostman.postExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
ExecutorExceptionHandler.handleException(ex);
return 0;
}
postExecutionEventsAfterExecution(statementExecutorWrapper);
eventPostman.postExecutionEventsAfterExecution(statementExecutorWrapper);
return result;
}
......@@ -244,7 +246,7 @@ public final class StatementExecutor {
private boolean execute(final Executor executor) {
Context context = MetricsContext.start("ShardingStatement-execute");
postExecutionEvents();
eventPostman.postExecutionEvents();
final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
final Map<String, Object> dataMap = ExecutorDataMap.getDataMap();
try {
......@@ -255,7 +257,9 @@ public final class StatementExecutor {
@Override
public Boolean execute(final StatementExecutorWrapper input) throws Exception {
return executeInternal(executor, input, isExceptionThrown, dataMap);
synchronized (input.getStatement().getConnection()) {
return executeInternal(executor, input, isExceptionThrown, dataMap);
}
}
});
return (null == result || result.isEmpty()) ? false : result.get(0);
......@@ -272,42 +276,14 @@ public final class StatementExecutor {
try {
result = executor.execute(statementExecutorWrapper.getStatement(), statementExecutorWrapper.getSqlExecutionUnit().getSql());
} catch (final SQLException ex) {
postExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
eventPostman.postExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE, Optional.of(ex));
ExecutorExceptionHandler.handleException(ex);
return false;
}
postExecutionEventsAfterExecution(statementExecutorWrapper);
eventPostman.postExecutionEventsAfterExecution(statementExecutorWrapper);
return result;
}
private void postExecutionEvents() {
for (StatementExecutorWrapper each : statementExecutorWrappers) {
if (each.getDMLExecutionEvent().isPresent()) {
DMLExecutionEventBus.post(each.getDMLExecutionEvent().get());
} else if (each.getDQLExecutionEvent().isPresent()) {
DQLExecutionEventBus.post(each.getDQLExecutionEvent().get());
}
}
}
private void postExecutionEventsAfterExecution(final StatementExecutorWrapper statementExecutorWrapper) {
postExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS, Optional.<SQLException>absent());
}
private void postExecutionEventsAfterExecution(final StatementExecutorWrapper statementExecutorWrapper, final EventExecutionType eventExecutionType, final Optional<SQLException> exp) {
if (statementExecutorWrapper.getDMLExecutionEvent().isPresent()) {
DMLExecutionEvent event = statementExecutorWrapper.getDMLExecutionEvent().get();
event.setEventExecutionType(eventExecutionType);
event.setExp(exp);
DMLExecutionEventBus.post(event);
} else if (statementExecutorWrapper.getDQLExecutionEvent().isPresent()) {
DQLExecutionEvent event = statementExecutorWrapper.getDQLExecutionEvent().get();
event.setEventExecutionType(eventExecutionType);
event.setExp(exp);
DQLExecutionEventBus.post(event);
}
}
private interface Updater {
int executeUpdate(Statement statement, String sql) throws SQLException;
......
......@@ -34,6 +34,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
......@@ -111,12 +112,16 @@ public final class PreparedStatementExecutorTest {
ResultSet resultSet2 = mock(ResultSet.class);
when(preparedStatement1.executeQuery()).thenReturn(resultSet1);
when(preparedStatement2.executeQuery()).thenReturn(resultSet2);
when(preparedStatement1.getConnection()).thenReturn(mock(Connection.class));
when(preparedStatement2.getConnection()).thenReturn(mock(Connection.class));
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
List<ResultSet> actualResultSets = actual.executeQuery();
assertThat(actualResultSets, hasItem(resultSet1));
assertThat(actualResultSets, hasItem(resultSet2));
verify(preparedStatement1).executeQuery();
verify(preparedStatement2).executeQuery();
verify(preparedStatement1).getConnection();
verify(preparedStatement2).getConnection();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL("SELECT * FROM dual");
......@@ -152,11 +157,15 @@ public final class PreparedStatementExecutorTest {
SQLException exp = new SQLException();
when(preparedStatement1.executeQuery()).thenThrow(exp);
when(preparedStatement2.executeQuery()).thenThrow(exp);
when(preparedStatement1.getConnection()).thenReturn(mock(Connection.class));
when(preparedStatement2.getConnection()).thenReturn(mock(Connection.class));
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
List<ResultSet> actualResultSets = actual.executeQuery();
assertThat(actualResultSets, is(Arrays.asList((ResultSet) null, null)));
verify(preparedStatement1).executeQuery();
verify(preparedStatement2).executeQuery();
verify(preparedStatement1).getConnection();
verify(preparedStatement2).getConnection();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL("SELECT * FROM dual");
......@@ -190,10 +199,14 @@ public final class PreparedStatementExecutorTest {
PreparedStatementExecutorWrapper wrapper2 = createPreparedStatementExecutorWrapperForDML(preparedStatement2, "ds_1");
when(preparedStatement1.executeUpdate()).thenReturn(10);
when(preparedStatement2.executeUpdate()).thenReturn(20);
when(preparedStatement1.getConnection()).thenReturn(mock(Connection.class));
when(preparedStatement2.getConnection()).thenReturn(mock(Connection.class));
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
assertThat(actual.executeUpdate(), is(30));
verify(preparedStatement1).executeUpdate();
verify(preparedStatement2).executeUpdate();
verify(preparedStatement1).getConnection();
verify(preparedStatement2).getConnection();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL("DELETE FROM dual");
......@@ -229,10 +242,14 @@ public final class PreparedStatementExecutorTest {
SQLException exp = new SQLException();
when(preparedStatement1.executeUpdate()).thenThrow(exp);
when(preparedStatement2.executeUpdate()).thenThrow(exp);
when(preparedStatement1.getConnection()).thenReturn(mock(Connection.class));
when(preparedStatement2.getConnection()).thenReturn(mock(Connection.class));
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
assertThat(actual.executeUpdate(), is(0));
verify(preparedStatement1).executeUpdate();
verify(preparedStatement2).executeUpdate();
verify(preparedStatement1).getConnection();
verify(preparedStatement2).getConnection();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL("DELETE FROM dual");
......@@ -266,10 +283,14 @@ public final class PreparedStatementExecutorTest {
PreparedStatementExecutorWrapper wrapper2 = createPreparedStatementExecutorWrapperForDML(preparedStatement2, "ds_1");
when(preparedStatement1.execute()).thenReturn(false);
when(preparedStatement2.execute()).thenReturn(false);
when(preparedStatement1.getConnection()).thenReturn(mock(Connection.class));
when(preparedStatement2.getConnection()).thenReturn(mock(Connection.class));
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
assertFalse(actual.execute());
verify(preparedStatement1).execute();
verify(preparedStatement2).execute();
verify(preparedStatement1).getConnection();
verify(preparedStatement2).getConnection();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL("DELETE FROM dual");
......@@ -305,10 +326,14 @@ public final class PreparedStatementExecutorTest {
SQLException exp = new SQLException();
when(preparedStatement1.execute()).thenThrow(exp);
when(preparedStatement2.execute()).thenThrow(exp);
when(preparedStatement1.getConnection()).thenReturn(mock(Connection.class));
when(preparedStatement2.getConnection()).thenReturn(mock(Connection.class));
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
assertFalse(actual.execute());
verify(preparedStatement1).execute();
verify(preparedStatement2).execute();
verify(preparedStatement1).getConnection();
verify(preparedStatement2).getConnection();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL("DELETE FROM dual");
......@@ -342,10 +367,14 @@ public final class PreparedStatementExecutorTest {
PreparedStatementExecutorWrapper wrapper2 = createPreparedStatementExecutorWrapperForDQL(preparedStatement2, "ds_0");
when(preparedStatement1.execute()).thenReturn(true);
when(preparedStatement2.execute()).thenReturn(true);
when(preparedStatement1.getConnection()).thenReturn(mock(Connection.class));
when(preparedStatement2.getConnection()).thenReturn(mock(Connection.class));
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
assertTrue(actual.execute());
verify(preparedStatement1).execute();
verify(preparedStatement2).execute();
verify(preparedStatement1).getConnection();
verify(preparedStatement2).getConnection();
verify(eventCaller, times(4)).verifyDataSource("ds_0");
verify(eventCaller, times(4)).verifySQL("SELECT * FROM dual");
verify(eventCaller, times(4)).verifyParameters(Collections.emptyList());
......
......@@ -34,6 +34,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
......@@ -113,7 +114,9 @@ public final class StatementExecutorTest {
ResultSet resultSet1 = mock(ResultSet.class);
ResultSet resultSet2 = mock(ResultSet.class);
when(statement1.executeQuery(SELECT_FROM_DUAL)).thenReturn(resultSet1);
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(executorEngine);
actual.addStatement(wrapper1);
StatementExecutorWrapper wrapper2 = createStatementExecutorWrapperForDQL(statement2, "ds_1");
......@@ -122,7 +125,9 @@ public final class StatementExecutorTest {
assertThat(actualResultSets, hasItem(resultSet1));
assertThat(actualResultSets, hasItem(resultSet2));
verify(statement1).executeQuery(SELECT_FROM_DUAL);
verify(statement1).getConnection();
verify(statement2).executeQuery(SELECT_FROM_DUAL);
verify(statement2).getConnection();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL(SELECT_FROM_DUAL);
......@@ -158,6 +163,8 @@ public final class StatementExecutorTest {
SQLException exp = new SQLException();
when(statement1.executeQuery(SELECT_FROM_DUAL)).thenThrow(exp);
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(executorEngine);
actual.addStatement(wrapper1);
StatementExecutorWrapper wrapper2 = createStatementExecutorWrapperForDQL(statement2, "ds_1");
......@@ -166,6 +173,8 @@ public final class StatementExecutorTest {
assertThat(actualResultSets, is(Arrays.asList((ResultSet) null, null)));
verify(statement1).executeQuery(SELECT_FROM_DUAL);
verify(statement2).executeQuery(SELECT_FROM_DUAL);
verify(statement1).getConnection();
verify(statement2).getConnection();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL(SELECT_FROM_DUAL);
......@@ -199,6 +208,8 @@ public final class StatementExecutorTest {
Statement statement2 = mock(Statement.class);
when(statement1.executeUpdate(DELETE_FROM_DUAL)).thenReturn(10);
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(executorEngine);
actual.addStatement(wrapper1);
StatementExecutorWrapper wrapper2 = createStatementExecutorWrapperForDML(statement2, "ds_1");
......@@ -206,6 +217,8 @@ public final class StatementExecutorTest {
assertThat(actual.executeUpdate(), is(30));
verify(statement1).executeUpdate(DELETE_FROM_DUAL);
verify(statement2).executeUpdate(DELETE_FROM_DUAL);
verify(statement1).getConnection();
verify(statement2).getConnection();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL(DELETE_FROM_DUAL);
......@@ -241,6 +254,8 @@ public final class StatementExecutorTest {
SQLException exp = new SQLException();
when(statement1.executeUpdate(DELETE_FROM_DUAL)).thenThrow(exp);
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(executorEngine);
actual.addStatement(wrapper1);
StatementExecutorWrapper wrapper2 = createStatementExecutorWrapperForDML(statement2, "ds_1");
......@@ -248,6 +263,8 @@ public final class StatementExecutorTest {
assertThat(actual.executeUpdate(), is(0));
verify(statement1).executeUpdate(DELETE_FROM_DUAL);
verify(statement2).executeUpdate(DELETE_FROM_DUAL);
verify(statement1).getConnection();
verify(statement2).getConnection();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL(DELETE_FROM_DUAL);
......@@ -332,6 +349,8 @@ public final class StatementExecutorTest {
Statement statement2 = mock(Statement.class);
when(statement1.execute(DELETE_FROM_DUAL)).thenReturn(false);
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(executorEngine);
actual.addStatement(wrapper1);
StatementExecutorWrapper wrapper2 = createStatementExecutorWrapperForDML(statement2, "ds_1");
......@@ -339,6 +358,8 @@ public final class StatementExecutorTest {
assertFalse(actual.execute());
verify(statement1).execute(DELETE_FROM_DUAL);
verify(statement2).execute(DELETE_FROM_DUAL);
verify(statement1).getConnection();
verify(statement2).getConnection();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL(DELETE_FROM_DUAL);
......@@ -374,6 +395,8 @@ public final class StatementExecutorTest {
SQLException exp = new SQLException();
when(statement1.execute(DELETE_FROM_DUAL)).thenThrow(exp);
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(executorEngine);
actual.addStatement(wrapper1);
StatementExecutorWrapper wrapper2 = createStatementExecutorWrapperForDML(statement2, "ds_1");
......@@ -381,6 +404,8 @@ public final class StatementExecutorTest {
assertFalse(actual.execute());
verify(statement1).execute(DELETE_FROM_DUAL);
verify(statement2).execute(DELETE_FROM_DUAL);
verify(statement1).getConnection();
verify(statement2).getConnection();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL(DELETE_FROM_DUAL);
......@@ -414,6 +439,8 @@ public final class StatementExecutorTest {
Statement statement2 = mock(Statement.class);
when(statement1.execute(SELECT_FROM_DUAL)).thenReturn(true);
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(executorEngine);
actual.addStatement(wrapper1);
StatementExecutorWrapper wrapper2 = createStatementExecutorWrapperForDQL(statement2, "ds_0");
......@@ -421,6 +448,8 @@ public final class StatementExecutorTest {
assertTrue(actual.execute());
verify(statement1).execute(SELECT_FROM_DUAL);
verify(statement2).execute(SELECT_FROM_DUAL);
verify(statement1).getConnection();
verify(statement2).getConnection();
verify(eventCaller, times(4)).verifyDataSource("ds_0");
verify(eventCaller, times(4)).verifySQL(SELECT_FROM_DUAL);
verify(eventCaller, times(4)).verifyParameters(Collections.emptyList());
......
+++
date = "2016-02-05T17:03:18+08:00"
title = "Release Notes"
......@@ -11,6 +12,12 @@ weight = 1
## 1.3.3
### 缺陷修正
1. [ISSUE #166](https://github.com/dangdangdotcom/sharding-jdbc/issues/166) druid数据源stat过滤器多线程报错
## 1.3.3
### 功能提升
1. [ISSUE #59](https://github.com/dangdangdotcom/sharding-jdbc/issues/59) PreparedStatement设置参数时可以根据参数类型调用正确的底层set方法
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册