https://blog.csdn.net/qq_20597727/article/details/84900994
或是数据库本身不支持, 如MySQL的Myisam.
不防看看是不是由多数据源引起的:
多数据源我们一般这样配置:
@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