@Transactional 在我的 Spring Boot 应用程序中无效

Posted

技术标签:

【中文标题】@Transactional 在我的 Spring Boot 应用程序中无效【英文标题】:@Transactional has no effect in my Spring Boot Application 【发布时间】:2019-03-08 19:47:50 【问题描述】:

这是一个非常令人困惑的问题。我已经阅读了几十个旨在解释如何使用 @Transactional 的链接,但我已经确认没有创建任何事务。

Main.java

@SpringBootApplication
@EnableJpaRepositories(basePackages="com.mypackage")
@EnableTransactionManagement
@EntityScan(basePackages=["com.mypackage"])
@EnableJpaAuditing
public class Main 
    public static void main(String[] args) 
        SpringApplication.run(Main.class, args);
    

订阅控制器.java

@RequestMapping("/api/subscription")
@RestController
public class SubscriptionController 
    @Autowired SubscriptionService subscriptionService;
    Logger log = LogManager.getLogger(this.getClass().getName());
    public Collection<Subscriptions> subscribe(...) 
        log.info("transName: " + TransactionSynchronizationManager.getCurrentTransactionName + ", isAlive: " + TransactionSynchronizationManager.isActualTransactionActive());
        return subscriptionService.getAllSubscriptions();
    
 

订阅服务.java

@Service
public class SubscriptionService 
    @Transactional public Collection<Subscription> getAllSubscriptions() 
        log.info("transName: " + TransactionSynchronizationManager.getCurrentTransactionName() + ", isAlive: " + TransactionSynchronizationManager.isActualTransactionActive());
        //return subscriptions via JPQL queries here
    

build.gradle

buildscript 
    repositories 
        mavenCentral()
    

    dependencies 
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.0.RELEASE")
    


plugins 
    id 'war'


apply plugin: 'org.springframework.boot'

repositories 
    mavenCentral()


def springVersion = '5.0.3.RELEASE'
dependencies 
    compile 'org.codehaus.groovy:groovy-all:2.3.11'
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile "org.springframework.security:spring-security-core:$springVersion", exclude
    compile "org.springframework.security:spring-security-config:$springVersion", exclude
    compile "org.springframework.security:spring-security-web:$springVersion", exclude
    testCompile group: 'junit', name: 'junit', version: '4.12'
    testCompile "org.springframework:spring-test:$springVersion", exclude
    implementation 'org.springframework.boot:spring-boot-starter-web:2.0.5.RELEASE', exclude
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.0.5.RELEASE'
    compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.11'
    compile 'org.liquibase:liquibase-core:3.6.1'
    compile 'org.liquibase:liquibase-groovy-dsl:1.2.2'

所以当我运行 api 调用时,我得到 null、false 作为日志输出。 @Transactional 的合约说事务方面的代码将被编织到带注释的事务方法中,这样就会在方法之前建立一个事务(以及一个实体管理器和数据库连接)并在一段时间后关闭。但这无关紧要,因为 spring 不应该在控制器运行之前创建实体管理器吗?这两件事在这里都行不通。 spring 和@Transactional 都没有设置任何事务。这导致无法执行任何类型的查询,除了通过 JpaRepository 的子类可以执行的操作。不知何故,我的 Jpa 存储库能够为自己的方法设置事务。但是,如果他们的结果具有延迟初始化的属性呢?我需要一个休眠会话来获得这些。所以我需要一笔交易。

【问题讨论】:

您是否将SubscriptionService 注释为弹簧管理的bean(@Service@Component 等)? @NiVeR 是的,我做到了。正在更新帖子中的代码... 在控制器中初始化订阅服务是什么意思? @VitaliiMuzalevskyi 我使用了“@Autowired”。更新了代码,以便您查看。谢谢评论 你在你的服务方法中实际做了什么?你能添加代码吗? 【参考方案1】:

尝试删除

@EnableJpaRepositories(basePackages="com.mypackage")
@EnableTransactionManagement

SpringBoot 应该自动完成这些事情

【讨论】:

刚刚删除了它们。效果是一样的。我已经添加了这些,认为它们可能会有所作为。【参考方案2】:

@Transactional 使用什么类? 你应该使用org.springframework.transaction.annotation.Transactional

【讨论】:

我正在使用 javax.transaction.Transactional。这是 JPA 类,对吧? 我把它改成了 org.springframework.transaction.annotation.Transactional。效果是一样的。日志输出中显示 null、false。 @Calicoder 你能把所有导入的整个代码放在某个地方吗?【参考方案3】:

使用 spring 初始化程序 (https://start.spring.io/) 的开箱即用 Spring-boot 应用程序将正确处理事务。如果您让自己成为一个带有单元测试的沙箱,您可以观察到在您的示例中完成的事务划分将产生一个事务。这是我的 git hub 示例:https://github.com/skjenco/hibernateSandbox.git

代码:

@Test
@Transactional
public void test() 

    logger.info(TransactionSynchronizationManager.getCurrentTransactionName());
    .....

要使事务划分起作用,您必须位于由 Spring 管理的对象中(组件、服务、托管 Bean 等)。在上述情况下,您似乎处于 Spring 托管服务中。使用工作沙箱可能有助于解决您的问题——这就是我为解决令人困惑的休眠问题所做的工作。

【讨论】:

【参考方案4】:

您可能还想发布您的pom.xml 文件。应添加 spring-dataspring-tx 依赖项,以便自动配置器创建事务管理器。否则,显式创建一个事务管理器 bean 并再次运行代码。

您可以为org.springframework 启用TRACE 级别的日志,并查看事务管理器是否已初始化。 还要检查事务拦截器日志。使用logging.level.org.springframework.transaction.interceptor=TRACE

【讨论】:

以上是关于@Transactional 在我的 Spring Boot 应用程序中无效的主要内容,如果未能解决你的问题,请参考以下文章

spring @Transactional JDBC 模板 MySQL DB 不回滚

如何在 Spring Boot 中使用 @Transactional 注解

Spring @Transactional 和 JDBC 自动提交

@Transactional 注释 rollbackFor 值在 Spring Boot 中不起作用

如何扩展Spring Annotation @Transactional

@Transactional 仅针对少数例外传播事务