Spring Programmatic transaction within transaction

人盡茶涼 提交于 2019-12-11 11:37:44

问题


I have written below code doing below activities I created one transaction using Spring classes. Inserted one row. Created other transaction. Inserted another row. committed outer transaction. Rolledback inner transaction.

TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
    jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
    TransactionStatus trxstsInner= dsTrxMngr.getTransaction(null);
        jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");

dsTrxMngr.commit(trxstsOuter);
System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
dsTrxMngr.rollback(trxstsInner);
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());

I observed that both the rows are committed to DB !! The output is

trxstsOuter.isCompleted()true
trxstsInner.isCompleted()false
trxstsInner.isCompleted()true

Is it correct behavior ? Should not inner transaction be first committed/rollbacked before allowing outer transaction to commit ? If outer transaction was committed, should rollback of inner thrown an error ?


回答1:


In your example transaction Propagation.REQUIRED is used as the default value, and all the logic transactions are mapped to the single physical transaction

When the propagation setting is PROPAGATION_REQUIRED, a logical transaction scope is created for each method upon which the setting is applied. Each such logical transaction scope can determine rollback-only status individually, with an outer transaction scope being logically independent from the inner transaction scope. Of course, in case of standard PROPAGATION_REQUIRED behavior, all these scopes will be mapped to the same physical transaction. So a rollback-only marker set in the inner transaction scope does affect the outer transaction's chance to actually commit (as you would expect it to).

So in your example two logical transactions are mapped to one physical transaction.

See the documentation




回答2:


In the current code the second getTransaction call is a noop. This behavior is controlled by an attribute called PropagationBehavior. The default propagation behavior is PROPAGATION_REQUIRED - which means that start a new transaction if none exists or else join the existing transaction. Which is what is happening in your case.

If you change the propagation behavior attribute for the second transaction to PROPAGATION_REQUIRES_NEW - you will get the behavior you are expected. The outer transaction is suspended and a new transaction is created once the inner transaction is committed/rolled back the outer transaction is resumed automatically. I have modified your code to incorporate this behavior, you should get an exception now when you try to commit the outer transaction before the inner one. If you fix the sequence then the commits will happen independently.

TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
    // start a new transaction.
    DefaultTransactionDefinition nestedTransDef = new DefaultTransactionDefinition();
    nestedTransDef.setPropagationBehavior(             
           TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    TransactionStatus trxstsInner= dsTrxMngr.getTransaction(nestedTransDef);
     System.out.println("trxstsInner.isNewTransaction()"+ trxstsInner.isNewTransaction());  
        jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");

dsTrxMngr.commit(trxstsOuter);
    System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
    dsTrxMngr.rollback(trxstsInner);
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());

As an aside you should be using annotations for managing transactions -that is a much cleaner / nicer way of incorporating transactions in your code. Programmatic transactions are only for those rare cases where you need more control. Also while doing programmatic transaction using the TransactionTemplate is recommended.



来源:https://stackoverflow.com/questions/13786816/spring-programmatic-transaction-within-transaction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!