【问题标题】:Transaction is required to perform this operation (either use a transaction or extended persistence context) while persisting Entity在持久化实体时需要事务来执行此操作(使用事务或扩展持久性上下文)
【发布时间】:2021-04-26 12:34:27
【问题描述】:

我正在尝试开发一个以特定间隔运行并执行一些数据库修改的类。

我设法以特定时间间隔运行的代码,从数据库中检索记录,但是当我想提交对数据库的更改时,我收到以下错误。

WFLYEE0110: Failed to run scheduled task: javax.persistence.TransactionRequiredException: WFLYJPA0060: Transaction is required to perform this operation (either use a transaction or extended persistence context)

是否允许@ApplicationScoped 创建事务?

谢谢!

@ApplicationScoped
@ActivateRequestContext
public class TaskRunner {

 @PersistenceContext(type = PersistenceContextType.EXTENDED)
  EntityManager em; 

  @Resource private ManagedScheduledExecutorService scheduler;

  private ScheduledFuture<?> TaskRunnerScheduler;

  private boolean initialized = false;

  private void init(@Observes @Initialized(ApplicationScoped.class) Object init) {

    if (initialized) return;

   
    initialized = true;
    try {
      // Execute at startup
      TaskRunner = scheduler.schedule(this::runSchedule, getSchedule());
    } catch (Throwable throwable) {

    }
  }

 @Transactional
  private void runSchedule() {
//retrieve db records
//make changes and commit
//sample
//em.persist(someEntity)
  }

  private Trigger getSchedule() {
    return new Trigger() {
      @Override
      public Date getNextRunTime(LastExecution lastExecutionInfo, Date taskScheduledTime) {
        return Date.from(
            ZonedDateTime.now().withSecond(0).withNano(0).plusHours("4").toInstant());
      }

      @Override
      public boolean skipRun(LastExecution lastExecutionInfo, Date scheduledRunTime) 
       {return false;}};
  }

}

【问题讨论】:

    标签: jpa cdi entitymanager java-ee-8


    【解决方案1】:

    事务通过拦截器启动。 当您从 bean 内部调用 bean 的方法时,方法调用不会被拦截,也不会启动任何 Transaction。

    你需要另一个 Bean 并坚持在那里

    @RequestScoped
    @Transactional(value = TxType.REQUIRES_NEW)
    public class SomeOtherBean{
    
        @PersistenceContext(type = PersistenceContextType.EXTENDED)
        EntityManager em;
        
        public void doSomething(){
             //retrieve db records
             //make changes and commit
             //sample
             //em.persist(someEntity)
        }
    }
    

    然后你可以在你的TaskRunner中注入那个bean

    @ApplicationScoped
    @ActivateRequestContext
    public class TaskRunner {
    
        @Inject
        SomeOtherBean someBean;
    
        ...
    
        private void runSchedule() {
            someBean.doSomething()
        }
    
    }
    

    【讨论】:

    • 我进行了更改,但出现了新错误。无法运行计划任务:org.jboss.weld.contexts.ContextNotActiveException:WELD-001303:范围类型 javax.enterprise.context.RequestScoped 没有活动上下文
    • 那么请尝试将Scope改为@Dependent
    猜你喜欢
    • 2016-06-18
    • 2016-08-10
    • 2016-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-13
    • 2017-02-17
    相关资源
    最近更新 更多