最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - How do I start a new sessiontransaction for each object in a job with a for-loop? - Stack Overflow

programmeradmin1浏览0评论

I am using Java EE, not Spring, in a Payara environment.

I have a job which goes through a list of objects called "position". For each position, a complex algorithm is run, which makes several calculations and changes some objects.

This job with the for-loop is either started by the user clicking a button or by a bean, which starts the job at a certain time.

Something like this:

public void processPositions(){
   for(Position position : shortPositions){
       try{
           for(Trade trade : borrowTrades){
        
               for(TradeEvent event : futureEvents){
                   cancelEvent(event);
               } // end for event
        
               closeTrade(trade);
           } // end for trade
       }catch(){
          // handle exception here
       }
   } // end for position
}

My problem is now, that, if a problem occurs when one position is processed, Hibernate rolls back the transaction, which is ok.

However, when the next position is taken, the run stops with the exception javax.ejb.EJBTransactionRolledbackException: Client's transaction aborted.

In principle, I would like to handle the changes for each position (and other corresponding objects) as a single transaction / session, which is independent from the others.

How can I achieve this?

I am a newbie to Hibernate. Without Hibernate, I would open a new transaction when I take the next position object in the loop. I would update/insert/delete the corresponding objects which are related to my position object by the use of SQL and in the end, I would commit everything or rollback. Then I would open a new transaction when taking the next object. However Hibernate is hiding this from the user. I believe that the call for processPositions is done within a session having a transaction. And if this transaction is rollbacked, it is used up. My question is how can I start a new transaction and make all the EntityManagers in the repositories use this new transaction when a persistent object is updated.

I am using Java EE, not Spring, in a Payara environment.

I have a job which goes through a list of objects called "position". For each position, a complex algorithm is run, which makes several calculations and changes some objects.

This job with the for-loop is either started by the user clicking a button or by a bean, which starts the job at a certain time.

Something like this:

public void processPositions(){
   for(Position position : shortPositions){
       try{
           for(Trade trade : borrowTrades){
        
               for(TradeEvent event : futureEvents){
                   cancelEvent(event);
               } // end for event
        
               closeTrade(trade);
           } // end for trade
       }catch(){
          // handle exception here
       }
   } // end for position
}

My problem is now, that, if a problem occurs when one position is processed, Hibernate rolls back the transaction, which is ok.

However, when the next position is taken, the run stops with the exception javax.ejb.EJBTransactionRolledbackException: Client's transaction aborted.

In principle, I would like to handle the changes for each position (and other corresponding objects) as a single transaction / session, which is independent from the others.

How can I achieve this?

I am a newbie to Hibernate. Without Hibernate, I would open a new transaction when I take the next position object in the loop. I would update/insert/delete the corresponding objects which are related to my position object by the use of SQL and in the end, I would commit everything or rollback. Then I would open a new transaction when taking the next object. However Hibernate is hiding this from the user. I believe that the call for processPositions is done within a session having a transaction. And if this transaction is rollbacked, it is used up. My question is how can I start a new transaction and make all the EntityManagers in the repositories use this new transaction when a persistent object is updated.

Share Improve this question edited Mar 3 at 14:38 DocU asked Feb 28 at 7:22 DocUDocU 313 bronze badges 2
  • The word process has a specific meaning in computing. Your use of that term here has a different meaning. I suggest you rewrite to avoid that. – Basil Bourque Commented Feb 28 at 7:43
  • You did not explain how the code shown relates to Hibernate nor to a EJB transaction. A minimal reproducible example would improve this Question. – Basil Bourque Commented Feb 28 at 7:46
Add a comment  | 

2 Answers 2

Reset to default 0

You could flush each item of your list. Otherwise you will have go over the transaction manager and initiate a transaction for each item. Then flush it, close the transaction and start all over again.

What you need, is to to tell Java EE to use a new transaction for your methods. The easiest way is to have a method with @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW):

@Stateless
public class ControlService {
   @EJB
   private TradeService tradeService;

   public void processPositions() {
       for(Position position : shortPositions) {
           tradeService.processPosition(position);
       }
   }
}

@Stateless
public class TradeService {
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public String processPosition(Position position) {
        // ... here is your business logic
    }
}

The first method, ControlService.processPositions() runs in the first transaction and each TradeService.processPosition() will have its own one.

发布评论

评论列表(0)

  1. 暂无评论