Support @⁠Sql with DataSource wrapped in a TransactionAwareDataSourceProxy

Prior to this commit, SqlScriptsTestExecutionListener unwrapped data
sources wrapped in an InfrastructureProxy or a scoped proxy, but it did
not unwrap a data source wrapped in a TransactionAwareDataSourceProxy.
Consequently, the sameDataSource() check failed in the latter case,
preventing execution of @⁠Sql scripts.

To address that, this commit revises sameDataSource() to unwrap a
TransactionAwareDataSourceProxy as well, analogous to the
implementations of setDataSource() in DataSourceTransactionManager,
JpaTransactionManager, and HibernateTransactionManager.

Closes gh-36611
This commit is contained in:
Sam Brannen
2026-04-08 17:13:14 +02:00
parent 3d211b71b1
commit 6251b2c0c9
2 changed files with 87 additions and 3 deletions
@@ -35,6 +35,7 @@ import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestContextAnnotationUtils;
@@ -389,10 +390,13 @@ public class SqlScriptsTestExecutionListener extends AbstractTestExecutionListen
* proxies as necessary to compare the target instances.
* @since 5.3.4
* @see TransactionSynchronizationUtils#unwrapResourceIfNecessary(Object)
* @see TransactionAwareDataSourceProxy#getTargetDataSource()
*/
private static boolean sameDataSource(DataSource ds1, DataSource ds2) {
return TransactionSynchronizationUtils.unwrapResourceIfNecessary(ds1)
.equals(TransactionSynchronizationUtils.unwrapResourceIfNecessary(ds2));
private static boolean sameDataSource(DataSource dataSource, DataSource dataSourceFromTxMgr) {
return (TransactionSynchronizationUtils.unwrapResourceIfNecessary(dataSource)
.equals(TransactionSynchronizationUtils.unwrapResourceIfNecessary(dataSourceFromTxMgr)) ||
(dataSource instanceof TransactionAwareDataSourceProxy tadsp &&
dataSourceFromTxMgr.equals(tadsp.getTargetDataSource())));
}
private @Nullable DataSource getDataSourceFromTransactionManager(PlatformTransactionManager transactionManager) {
@@ -0,0 +1,80 @@
/*
* Copyright 2002-present 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.test.context.jdbc;
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.transaction.PlatformTransactionManager;
/**
* Transactional integration tests for {@link Sql @Sql} support when the
* {@link DataSource} is wrapped in a {@link TransactionAwareDataSourceProxy}.
*
* @author Sam Brannen
* @since 6.2.18
*/
@SpringJUnitConfig
@DirtiesContext
class SqlScriptsAndTransactionAwareDataSourceProxyTests extends AbstractTransactionalTests {
@Test
@Sql("data-add-catbert.sql")
void onlyCatbertIsPresent() {
assertUsers("Catbert");
}
@Test
@Sql("data-add-dogbert.sql")
void onlyDogbertIsPresent() {
assertUsers("Dogbert");
}
@Configuration(proxyBeanMethods = false)
static class Config {
@Bean
JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
DataSource dataSource() {
DataSource dataSource = new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.addScript("classpath:/org/springframework/test/context/jdbc/schema.sql")
.build();
return new TransactionAwareDataSourceProxy(dataSource);
}
}
}