Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.0k views
in Technique[技术] by (71.8m points)

jpa - Transaction is required to perform this operation (either use a transaction or extended persistence context) while persisting Entity

I am trying to develop a class that runs at specific intervals and performs some DB modifications.

the code I have managed to run at a specific interval, retrieve records from the DB, but when I want to commit changes to the DB I get the following error.

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)

is @ApplicationScoped allowed to create transactions?

Thanks!

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

}
question from:https://stackoverflow.com/questions/65838443/transaction-is-required-to-perform-this-operation-either-use-a-transaction-or-e

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Transactions are started via Interceptors. When you call a method of a bean from inside that bean, the method-call is not intercepted and no Transaction can get started.

You need another Bean and persist in there

@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)
    }
}

then you can Inject that bean in your TaskRunner

@ApplicationScoped
@ActivateRequestContext
public class TaskRunner {

    @Inject
    SomeOtherBean someBean;

    ...

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

}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...