Stop using Constants utility in IsolationLevelDataSourceRouter
See gh-30851
This commit is contained in:
parent
181c814e69
commit
06c6af9b0d
|
|
@ -16,11 +16,12 @@
|
|||
|
||||
package org.springframework.jdbc.datasource.lookup;
|
||||
|
||||
import org.springframework.core.Constants;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* DataSource that routes to one of various target DataSources based on the
|
||||
|
|
@ -82,6 +83,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
|
|||
* </bean></pre>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 2.0.1
|
||||
* @see #setTargetDataSources
|
||||
* @see #setDefaultTargetDataSource
|
||||
|
|
@ -93,8 +95,17 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
|
|||
*/
|
||||
public class IsolationLevelDataSourceRouter extends AbstractRoutingDataSource {
|
||||
|
||||
/** Constants instance for TransactionDefinition. */
|
||||
private static final Constants constants = new Constants(TransactionDefinition.class);
|
||||
/**
|
||||
* Map of constant names to constant values for the isolation constants
|
||||
* defined in {@link TransactionDefinition}.
|
||||
*/
|
||||
static final Map<String, Integer> constants = Map.of(
|
||||
"ISOLATION_DEFAULT", TransactionDefinition.ISOLATION_DEFAULT,
|
||||
"ISOLATION_READ_UNCOMMITTED", TransactionDefinition.ISOLATION_READ_UNCOMMITTED,
|
||||
"ISOLATION_READ_COMMITTED", TransactionDefinition.ISOLATION_READ_COMMITTED,
|
||||
"ISOLATION_REPEATABLE_READ", TransactionDefinition.ISOLATION_REPEATABLE_READ,
|
||||
"ISOLATION_SERIALIZABLE", TransactionDefinition.ISOLATION_SERIALIZABLE
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -104,14 +115,16 @@ public class IsolationLevelDataSourceRouter extends AbstractRoutingDataSource {
|
|||
*/
|
||||
@Override
|
||||
protected Object resolveSpecifiedLookupKey(Object lookupKey) {
|
||||
if (lookupKey instanceof Integer) {
|
||||
return lookupKey;
|
||||
if (lookupKey instanceof Integer isolationLevel) {
|
||||
Assert.isTrue(constants.containsValue(isolationLevel),
|
||||
"Only values of isolation constants allowed");
|
||||
return isolationLevel;
|
||||
}
|
||||
else if (lookupKey instanceof String constantName) {
|
||||
if (!constantName.startsWith(DefaultTransactionDefinition.PREFIX_ISOLATION)) {
|
||||
throw new IllegalArgumentException("Only isolation constants allowed");
|
||||
}
|
||||
return constants.asNumber(constantName);
|
||||
Assert.hasText(constantName, "'lookupKey' must not be null or blank");
|
||||
Integer isolationLevel = constants.get(constantName);
|
||||
Assert.notNull(isolationLevel, "Only isolation constants allowed");
|
||||
return isolationLevel;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package org.springframework.jdbc.datasource.lookup;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.springframework.transaction.TransactionDefinition.ISOLATION_DEFAULT;
|
||||
import static org.springframework.transaction.TransactionDefinition.ISOLATION_READ_COMMITTED;
|
||||
import static org.springframework.transaction.TransactionDefinition.ISOLATION_READ_UNCOMMITTED;
|
||||
import static org.springframework.transaction.TransactionDefinition.ISOLATION_REPEATABLE_READ;
|
||||
import static org.springframework.transaction.TransactionDefinition.ISOLATION_SERIALIZABLE;
|
||||
|
||||
/**
|
||||
* Tests for {@link IsolationLevelDataSourceRouter}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 6.1
|
||||
*/
|
||||
class IsolationLevelDataSourceRouterTests {
|
||||
|
||||
private final IsolationLevelDataSourceRouter router = new IsolationLevelDataSourceRouter();
|
||||
|
||||
|
||||
@Test
|
||||
void resolveSpecifiedLookupKeyForInvalidTypes() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> router.resolveSpecifiedLookupKey(new Object()));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> router.resolveSpecifiedLookupKey('X'));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveSpecifiedLookupKeyByNameForUnsupportedValues() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> router.resolveSpecifiedLookupKey(null));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> router.resolveSpecifiedLookupKey(" "));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> router.resolveSpecifiedLookupKey("bogus"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the internal 'constants' map is properly configured for all
|
||||
* ISOLATION_ constants defined in {@link TransactionDefinition}.
|
||||
*/
|
||||
@Test
|
||||
void resolveSpecifiedLookupKeyByNameForAllSupportedValues() {
|
||||
Set<Integer> uniqueValues = new HashSet<>();
|
||||
streamIsolationConstants()
|
||||
.forEach(name -> {
|
||||
Integer isolationLevel = (Integer) router.resolveSpecifiedLookupKey(name);
|
||||
Integer expected = IsolationLevelDataSourceRouter.constants.get(name);
|
||||
assertThat(isolationLevel).isEqualTo(expected);
|
||||
uniqueValues.add(isolationLevel);
|
||||
});
|
||||
assertThat(uniqueValues).containsExactlyInAnyOrderElementsOf(IsolationLevelDataSourceRouter.constants.values());
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveSpecifiedLookupKeyByInteger() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> router.resolveSpecifiedLookupKey(999));
|
||||
|
||||
assertThat(router.resolveSpecifiedLookupKey(ISOLATION_DEFAULT)).isEqualTo(ISOLATION_DEFAULT);
|
||||
assertThat(router.resolveSpecifiedLookupKey(ISOLATION_READ_UNCOMMITTED)).isEqualTo(ISOLATION_READ_UNCOMMITTED);
|
||||
assertThat(router.resolveSpecifiedLookupKey(ISOLATION_READ_COMMITTED)).isEqualTo(ISOLATION_READ_COMMITTED);
|
||||
assertThat(router.resolveSpecifiedLookupKey(ISOLATION_REPEATABLE_READ)).isEqualTo(ISOLATION_REPEATABLE_READ);
|
||||
assertThat(router.resolveSpecifiedLookupKey(ISOLATION_SERIALIZABLE)).isEqualTo(ISOLATION_SERIALIZABLE);
|
||||
}
|
||||
|
||||
|
||||
private static Stream<String> streamIsolationConstants() {
|
||||
return Arrays.stream(TransactionDefinition.class.getFields())
|
||||
.filter(ReflectionUtils::isPublicStaticFinal)
|
||||
.map(Field::getName)
|
||||
.filter(name -> name.startsWith("ISOLATION_"));
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue