Quarkus中子线程@Transactional注解不生效报错如何解决?
问题根本原因
你手动new DataTask()创建的实例不属于Quarkus CDI容器的托管对象,加在run()方法上的@Transactional注解是基于AOP拦截实现的,只有容器托管的Bean调用被注解的方法才会触发事务开启逻辑,自定义实例的注解不会被识别,所以执行persist时没有活跃事务。
解决方案1:将DataTask改为CDI托管Bean(推荐)
- 给DataTask类加
@Dependent注解,声明为CDI Bean - 注入
Instance<DataTask>动态获取实例,避免参数传递冲突
修改后的代码示例:
TaskController修改
@RequestScoped @Path("/task/ledger") public class TaskController { // 注入DataTask的实例工厂 @Inject Instance<DataTask> dataTaskInstance; ExecutorService threadPool = Executors.newFixedThreadPool(10); @Transactional @POST @Path("/start/{id}") public int createLedgerTask(@PathParam("id") String id) { LedgerTaskOverview overview = LedgerTaskOverview.findById(id); // 从容器获取托管实例,不要自己new DataTask task = dataTaskInstance.get(); // 手动设置参数 task.init(overview, dnsServer, elasticSearchClient); threadPool.execute(task); return 0; } }
DataTask修改
@Dependent // 声明为CDI托管Bean public class DataTask implements Runnable { private LedgerTaskOverview overview; private DNSServer dnsServer; private ElasticSearchClient elasticSearchClient; // 提供初始化方法设置参数 public void init(LedgerTaskOverview overview, DNSServer dnsServer, ElasticSearchClient elasticSearchClient) { this.overview = overview; this.dnsServer = dnsServer; this.elasticSearchClient = elasticSearchClient; } @Transactional @Override public void run() { ManagedContext requestContext = Arc.container().requestContext(); boolean contextCreated = false; if (!requestContext.isActive()) { requestContext.activate(); contextCreated = true; } try { //执行业务逻辑,若提示实体游离可改为 overview.getEntityManager().merge(overview) overview.persist(); } finally { // 用完手动销毁请求上下文,避免内存泄漏 if (contextCreated) { requestContext.deactivate(); requestContext.destroy(); } } } }
解决方案2:使用编程式事务手动控制(无需改Bean托管)
如果你不想把DataTask改成托管Bean,可以直接在run方法里手动开启/提交事务:
public class DataTask implements Runnable { public DataTask(LedgerTaskOverview overview, DNSServer dnsServer, ElasticSearchClient elasticSearchClient) { this.overview = overview; this.dnsServer = dnsServer; this.elasticSearchClient = elasticSearchClient; } // 不需要@Transactional注解 @Override public void run() { ManagedContext requestContext = Arc.container().requestContext(); boolean contextCreated = false; if (!requestContext.isActive()) { requestContext.activate(); contextCreated = true; } // 手动控制事务 QuarkusTransaction.begin(); try { // 若提示实体游离可改为 overview.getEntityManager().merge(overview) overview.persist(); QuarkusTransaction.commit(); } catch (Exception e) { QuarkusTransaction.rollback(); throw new RuntimeException("事务执行失败", e); } finally { if (contextCreated) { requestContext.deactivate(); requestContext.destroy(); } } } }
内容的提问来源于stack exchange,提问作者庞启荣
相关产品推荐
相关产品推荐

