我正在使用 Timefold 1.15 和 Quarkus 3.1
我正在尝试在解决时间表的过程中保存数据
但我有一些在解决过程中需要的上下文,行安全性的租户上下文和身份上下文
但我面临与上下文不可用相关的问题
示例代码:
solverManager.solveBuilder()
.withProblemId(finalRequestId)
.withProblemFinder((id) -> timeTableJob.get(finalRequestId).timetable)
.withBestSolutionConsumer(bestSolution -> timeTableJob.put(finalRequestId, Job.ofTimetable(bestSolution)))
.withFinalBestSolutionConsumer(solution -> {
timeTableJob.put(finalRequestId,Job.ofTimetable(solution));
plannedLessonRepository.save(solution);
})
.withExceptionHandler((id, exception) -> {
timeTableJob.put(finalRequestId, Job.ofException(exception));
LOGGER.error("Failed solving jobId ({}).", finalRequestId, exception);
})
.run();
错误:
2024-11-26 17:18:32,463 错误 [org.acm.sch.res.TimeTableResource] (pool-13-thread-1) 无法解决 jobId (101)。:org.hibernate.HibernateException:SessionFactory 配置为多租户,但未在 org.hibernate.internal.AbstractSharedSessionContract.getTenantId(AbstractSharedSessionContract.java:292) 处指定租户标识符,在 org.hibernate.internal.AbstractSharedSessionContract.(AbstractSharedSessionContract.java:193) 处指定租户标识符,在 org.hibernate.internal.SessionImpl.(SessionImpl.java:230) 处指定 org.hibernate.internal.SessionFactoryImpl$SessionBuilderImpl.openSession(SessionFactoryImpl.java:1381) 处指定org.hibernate.internal.SessionFactoryImpl$SessionBuilderImpl.openSession(SessionFactoryImpl.java:1247) at io.quarkus.hibernate.orm.runtime.session.JTASessionOpener.openSession(JTASessionOpener.java:46) at io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession.acquireSession(TransactionScopedSession.java:92) at io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession.find(TransactionScopedSession.java:175) at org.hibernate.engine.spi.SessionLazyDelegator.find(SessionLazyDelegator.java:825) at org.hibernate.Session_OpdLahisOZ9nWRPXMsEFQmQU03A_Synthetic_ClientProxy.find(Unknown Source) at io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations.findById(AbstractJpaOperations.java:183) at org.acme.timetable.persistence.PlannedLessonRepository.findById(PlannedLessonRepository.java) at org.acme.timetable.persistence.PlannedLessonRepository.findById(PlannedLessonRepository.java) at org.acme.timetable.persistence.PlannedLessonRepository.save(PlannedLessonRepository.java:24) at org.acme.timetable.persistence.PlannedLessonRepository_Subclass.save$$superforward(未知来源) at org.acme.timetable.persistence.PlannedLessonRepository_Subclass$$function$$1.apply(未知来源) at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:73) at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:62) at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.invokeInOurTx(TransactionalInterceptorBase.java:136) at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.invokeInOurTx(TransactionalInterceptorBase.java:107) at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired.doIntercept(TransactionalInterceptorRequired.java:38) at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.intercept(TransactionalInterceptorBase.java:61) at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired.intercept(TransactionalInterceptorRequired.java:32) at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired_Bean.intercept(Unknown Source) at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42) at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:30) 在 io.quarkus.arc.impl。InvocationContexts.performAroundInvoke(InvocationContexts.java:27) at org.acme.timetable.persistence.PlannedLessonRepository_Subclass.save(未知来源) at org.acme.timetable.persistence.PlannedLessonRepository_ClientProxy.save(未知来源) at org.acme.timetable.rest.TimeTableResource.lambda$solve$2(TimeTableResource.java:112) at ai.timefold.solver.core.impl.solver.ConsumerSupport.lambda$consumeFinalBestSolution$1(ConsumerSupport.java:102) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) 在 java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) 在 java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) 在 java.base/java.lang.Thread.run(Thread.java:833)
最佳解决方案消费者、最终最佳解决方案消费者和异常处理程序在与接受 API 调用的线程不同的线程中运行。因此,事务的上下文不会被传播。
您可以做的是使用QuarkusTransaction在最终最佳解决方案消费者中启动和结束事务(并删除
@Transactional
注释)。