简体   繁体   English

如何在执行长任务之前完成容器管理的事务?

[英]How to finish a container-managed transaction before running a long task?

I have a task which consists of 3 steps prepare , execute , update . 我的任务包括prepareexecuteupdate 3个步骤。 prepare and update need to work within a transaction, whereas execute takes very long (ie several minutes up to hours). prepareupdate需要在事务中工作,而execute需要很长时间(即几分钟到几小时)。 The task is part of an EJB, ie: 该任务是EJB的一部分,即:

@Stateless
public class Task {
    public void doTask() {
        prepare();
        execute();
        update();
    }
}

My question is, is there an (elegant) way to commit and finish the transaction after prepare and start a new one before update ? 我的问题是,在prepare并在update之前启动新事务之后,是否有(优雅)的方法来提交和完成事务? I'd rather use container-managed transactions and possibly not switch to use UserTransaction . 我宁愿使用容器管理的事务,也可能不切换为使用UserTransaction

It is possible to split the tasks into single EJBs if it gains any advantage, but note that suspending the transaction for execute (ie using @Transactional(TxType.NOT_SUPPORTED) is not enough since this still triggers the timeout. 如果有优势,可以将任务拆分为单个EJB,但是请注意,暂停事务以execute (即,使用@Transactional(TxType.NOT_SUPPORTED)是不够的,因为这仍会触发超时。

I tried to split it into a TaskExecute class which has @Asynchronous @Transactional(NOT_SUPPORTED) public void execute() and sending an event when done. 我试图将其拆分为具有@Asynchronous @Transactional(NOT_SUPPORTED) public void execute()TaskExecute类,并在完成后发送事件。 But this doesn't seem to work either. 但这似乎也不起作用。

Is there a way to do this? 有没有办法做到这一点?


After some further testing let me conclude: Alexanders reply was absolutely correct. 经过进一步的测试后,我得出结论:亚历山大的回答是绝对正确的。 My understanding had to be altered. 我的理解必须改变。 Foremost, I wasn't aware that @Transactional does not work on EJBs, but only on CDI beans. 首先,我不知道@Transactional不适用于EJB,而仅适用于CDI bean。 For EJBs the annotation is called @TransactionAttribute and can be set to basically the same values. 对于EJB,注释称为@TransactionAttribute ,可以将其设置为基本上相同的值。 A combination of @Asynchronous and @TransactionAttribute(NOT_SUPPORTED) does work (if not waiting for the result). @Asynchronous@TransactionAttribute(NOT_SUPPORTED)确实有效(如果不等待结果)。

It depends on the version of Java EE you want to use. 这取决于您要使用的Java EE版本。 Here are three possible solutions. 这是三种可能的解决方案。

  • use JMS, send an appropriate message and do the execute in the MDB (any version, but full profile required) 使用JMS,发送适当的消息并在MDB中execute (任何版本,但需要完整的概要文件)
  • use Java EE 6.0's Timer Service and schedule a task to perform the execute asynchronously ( @Timeout ) 使用Java EE 6.0的Timer Service并计划任务以异步执行execute@Timeout
  • use Java EE 7.0's Batch Processing API to schedule a proper long running batch job. 使用Java EE 7.0的批处理API安排适当的长期运行的批处理作业。

The latter is probably what you are looking for, but only available in Java EE 7.0 and up. 后者可能是您要寻找的,但是仅在Java EE 7.0及更高版本中可用。 Otherwise, the JMS solutions is the cleanest, but if JMS is not an option, the Timer Service should work. 否则,JMS解决方案是最干净的,但是如果不能选择JMS,则Timer Service应该可以工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM