You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring MVC迁移Spring Reactive后实体状态未变更问题求助

问题根源分析

你的代码里有几个核心问题导致实体状态没能同步到数据库:

  1. 阻塞调用破坏Reactive上下文:visitRequestDao.findById(requestId).get()是同步阻塞调用,在Reactive环境(比如Netty线程)中执行会导致Hibernate Session提前关闭——同步JPA操作完成后Session通常会被立即释放,后续的request.approve()修改发生在Session关闭之后,Hibernate无法捕获这些脏数据变更。
  2. 缺少Reactive事务支持:传统的@Transactional注解是为同步场景设计的,在Reactive流中无法正确管理事务边界,导致修改后的实体没有被提交到数据库。
  3. Reactive流与JPA同步API不兼容:原生JPA是同步模型,直接在Reactive流中调用同步DAO方法会打破Session和事务的生命周期管理。
具体解决方案

1. 切换到Reactive持久化API(推荐:Hibernate Reactive)

如果要在Spring Reactive中继续使用Hibernate,建议迁移到Hibernate Reactive,它提供了原生的Reactive API,完美适配Reactor的Mono/Flux。

步骤:

  • 添加Hibernate Reactive依赖(Maven示例):
<dependency>
    <groupId>org.hibernate.reactive</groupId>
    <artifactId>hibernate-reactive-core</artifactId>
    <version>2.2.2.Final</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <!-- 排除同步Hibernate依赖 -->
    <exclusions>
        <exclusion>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  • 配置Reactive数据源和事务管理器:
@Configuration
public class ReactiveHibernateConfig {
    @Bean
    public HibernateReactiveSessionFactory sessionFactory(EntityManagerFactory emf) {
        return emf.unwrap(HibernateReactiveSessionFactory.class);
    }

    @Bean
    public ReactiveTransactionManager reactiveTransactionManager(HibernateReactiveSessionFactory sessionFactory) {
        return new HibernateReactiveTransactionManager(sessionFactory);
    }
}
  • 重构DAO为Reactive风格:
public interface VisitRequestDao {
    Mono<VisitRequest> findById(Long requestId);
    Mono<VisitRequest> save(VisitRequest visitRequest);
}

@Repository
public class VisitRequestDaoImpl implements VisitRequestDao {
    private final HibernateReactiveSessionFactory sessionFactory;

    public VisitRequestDaoImpl(HibernateReactiveSessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    public Mono<VisitRequest> findById(Long requestId) {
        return Mono.fromCompletionStage(sessionFactory.withSession(session -> session.find(VisitRequest.class, requestId)));
    }

    @Override
    public Mono<VisitRequest> save(VisitRequest visitRequest) {
        return Mono.fromCompletionStage(sessionFactory.withSession(session -> session.persist(visitRequest).thenApply(v -> visitRequest)));
    }
}

2. 修正Reactive流中的事务与Session管理(兼容同步JPA过渡方案)

如果暂时无法切换到Hibernate Reactive,需要解决同步JPA调用的线程问题和事务问题:

修正后的代码示例:

@Service
public class VisitRequestService {
    private final VisitRequestDao visitRequestDao;
    private final ReactiveTransactionTemplate transactionTemplate;

    public VisitRequestService(VisitRequestDao visitRequestDao, ReactiveTransactionTemplate transactionTemplate) {
        this.visitRequestDao = visitRequestDao;
        this.transactionTemplate = transactionTemplate;
    }

    public Mono<ResponseEntity<List<PendingVisitRequest>>> approveRequest(Long requestId, Owner owner) {
        return transactionTemplate.execute(status ->
                // 将同步JPA调用切换到弹性线程池,避免阻塞Netty EventLoop
                Mono.fromSupplier(() -> visitRequestDao.findById(requestId).get())
                        .subscribeOn(Schedulers.boundedElastic())
                        .map(request -> {
                            request.approve();
                            return request;
                        })
                        .doOnNext(visitRequestDao::save)
        ).map(request -> ResponseEntity.ok(listOfPendingVisitRequest(owner)));
    }
}

3. 关键注意事项

  • 永远不要在Reactor的EventLoop线程中执行阻塞操作:所有同步JPA调用必须通过subscribeOn(Schedulers.boundedElastic())切换到专门的阻塞线程池。
  • 使用Reactive事务注解:如果使用Spring Boot 2.3+,可以使用@Transactional配合Reactive事务管理器,或者明确指定@Transactional(transactionManager = "reactiveTransactionManager")。
  • 确保修改操作在Session/事务范围内:Hibernate的脏检查仅在Session活跃且事务提交时生效,所以实体的修改必须在打开的Session和事务中完成。

内容的提问来源于stack exchange,提问作者Alberto Souza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:40:29