如果你已经排除了以下问题:
https://blog.csdn.net/qq_20597727/article/details/84900994
或是数据库本身不支持, 如MySQL的Myisam.
不防看看是不是由多数据源引起的:
多数据源我们一般这样配置:
class="java" name="code">
@Configuration
@EnableDataSource("A")
@EnableJpaRepositories(
repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class,
entityManagerFactoryRef = "defaultEntityManagerFactory",
basePackages = {"com.A.dao"},
transactionManagerRef = "defaultTransactionManager"
)
@ConditionalOnProperty(
prefix = "XXX.datasource.default",
name = {"driverClassName", "url", "username", "password"}
)
protected static class DataSourceDefaultConfiguration {
private static final Logger log = LoggerFactory.getLogger(DataSourceConfiguration.DataSourceDefaultConfiguration.class);
protected DataSourceDefaultConfiguration() {
}
}
@Configuration
@EnableDataSource("B")
@EnableJpaRepositories(
repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class,
entityManagerFactoryRef = "myGblEntityManagerFactory",
basePackages = {"com.B.dao"},
transactionManagerRef = "myGblTransactionManager"
)
@ConditionalOnProperty(
prefix = "XXX.datasource.myGbl",
name = {"driverClassName", "url", "username", "password"}
)
protected static class DataSourceMyGblConfiguration {
private static final Logger log = LoggerFactory.getLogger(DataSourceConfiguration.DataSourceMyGblConfiguration.class);
protected DataSourceMyGblConfiguration() {
}
}
这样, 其中一个数据源就是默认的数据源, 如A. 如果使用@Transaction注解开启事务, 默认使用默认数据源A来进行开启, 提交, 回滚 事务, 这个时候如果@Transaction方法里面是对com.B.dao进行的操作, 那么其实事务也是作用在A数据源上, 就会产生事务不生效的假象.
这时需指定事务对象来声明事务: @Transactional(value = "myGblTransactionManager"), 这时事务会作用在com.B.dao的操作上.
关于事务是否生效, 可以从这里入手检查:
org.springframework.orm.jpa.JpaTransactionManager
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
JpaTransactionObject txObject = (JpaTransactionObject) transaction;
if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
throw new IllegalTransactionStateException(
"Pre-bound JDBC Connection found! JpaTransactionManager does not support " +
"running within DataSourceTransactionManager if told to manage the DataSource itself. " +
"It is recommended to use a single JpaTransactionManager for all transactions " +
"on a single DataSource, no matter whether JPA or JDBC access.");
}
try {
if (!txObject.hasEntityManagerHolder() ||
txObject.getEntityManagerHolder().isSynchronizedWithTransaction()) {
如果是非JpaTransactionManager, 可以从其接口入手PlatformTransactionManager