Для выполнения этой операции требуется транзакция (либо использовать транзакцию, либо расширенный контекст сохранения) при сохранении объекта

#jpa #cdi #entitymanager #java-ee-8

#jpa #cdi #entitymanager #java-ee-8

Вопрос:

Я пытаюсь разработать класс, который выполняется с определенными интервалами и выполняет некоторые модификации БД.

код, который мне удалось запустить с определенным интервалом, извлекает записи из БД, но когда я хочу зафиксировать изменения в БД, я получаю следующую ошибку.

 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;}};
  }

}
 

Ответ №1:

Транзакции запускаются с помощью перехватчиков. Когда вы вызываете метод компонента изнутри этого компонента, вызов метода не перехватывается, и транзакция не может быть запущена.

Вам нужен другой компонент и сохраняться там

 @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

 @ApplicationScoped
@ActivateRequestContext
public class TaskRunner {

    @Inject
    SomeOtherBean someBean;

    ...

    private void runSchedule() {
        someBean.doSomething()
    }

}
 

Комментарии:

1. Я внес изменения, но получаю новую ошибку. Не удалось запустить запланированную задачу: org.jboss.weld.contexts. ContextNotActiveException: WELD-001303: нет активных контекстов для области видимости типа javax.enterprise.context.RequestScoped

2. Затем, пожалуйста, попробуйте изменить область видимости на @Dependent