Spring transaction attributes

Source: Internet
Author: User
Tags savepoint
  • Spring declarative transactions free us from complicated transaction processing. So that we no longer need to process such operations as getting a connection, closing a connection, committing a transaction, and rolling back. There is no need to process a large number of try methods in transaction-related methods... Catch... Finally code.
    When we use spring declarative transactions, a very important concept is the transaction attributes. The transaction attribute is usually composed of the Propagation Behavior of the transaction, the isolation level of the transaction, the transaction timeout value and the transaction read-only mark. When dividing a transaction, we need to define the transaction, that is, to configure the transaction attributes.
    SpringTransactiondefinitionThese attributes are defined in the interface for platfromtransactionmanager. platfromtransactionmanager is the core interface of Spring transaction management.

    1. transactiondefinition
    2. Public interface transactiondefinition ...{
    3. Int getpropagationbehavior ();
    4. Int getisolationlevel ();
    5. Int gettimeout ();
    6. boolean isreadonly ();
    7 .}

    The gettimeout () method returns the number of seconds that the transaction must be completed.
    Isreadonly (): whether the transaction is read-only. The transaction manager can optimize the transaction based on the returned value to ensure that the transaction is read-only.
    The getisolationlevel () method returns the isolation level of the transaction. The transaction manager controls the data in another transaction according to it.

    Five different transaction isolation levels are defined in the transactiondefinition interface.
    Isolation_defaultThis is the default isolation level of platfromtransactionmanager, which uses the default transaction isolation level of the database. The other four correspond to the JDBC isolation level.
    Isolation_read_uncommittedThis is the lowest isolation level of the transaction. It allows others to see the uncommitted data of this transaction. This isolation level will generate dirty reads, which cannot be repeated and Phantom reads.
    For example:
    Mary's original salary was 1000, and the finance staff changed Mary's salary to 8000, but did not submit the transaction

    1. Connection con1 = getConnection();     2. con.setAutoCommit(false);     3. update employee set salary = 8000 where empId ="Mary";

    At the same time, Mary is reading her own salary

    1. Connection con2 = getConnection();     2. select  salary from employee where empId ="Mary";     3. con2.commit();

    Mary found her salary changed to 8000!
    While the financial team found that the operation was wrong, and rolled back the transaction, Mary's salary changed to 1000

    # //con1  #   con1.rollback();

    In this way, 8000 of Mary's salary is a dirty data.

    Isolation_read_committedEnsure that the modified data of one transaction can be read by another transaction only after it is committed. Another transaction cannot read the uncommitted data of the transaction. This transaction isolation level can avoid dirty reads, but may cause non-repeated reads and Phantom reads.

    Isolation_repeatable_readThis transaction isolation level prevents dirty reads and does not allow repeated reads. However, phantom reading may occur. In addition to ensuring that one transaction cannot read the uncommitted data of another transaction, it also ensures that the following situations are avoided (non-repeated reads ).

    In transaction 1, Mary reads her salary of 1000, and the operation is not completed.

    1. con1 = getConnection();     2. select salary from employee empId ="Mary";

    In transaction 2, the financial staff changed Mary's salary to 2000 and committed the transaction.

    1. con2 = getConnection();     2. update employee set salary = 2000;     3. con2.commit();

    In transaction 1, when Mary reads her salary again, the salary changes to 2000.

    # //con1  # select salary from employee empId ="Mary";

    The result of two reads before and after a transaction is inconsistent, resulting in non-repeated reads.
    This can be avoided by using isolation_repeatable_read.

    Isolation_serializableThis is the most costly but most reliable transaction isolation level. Transactions are processed in sequence. In addition to preventing dirty reads and not repeated reads, Phantom reads are also avoided.

    Currently, there are 10 employees with a salary of 1000.
    Transaction 1 reads all employees whose salaries are 1000.

    1. con1 = getConnection();     2. Select * from employee where salary =1000;

    Read 10 records in total

    At this time, another transaction inserts an employee record into the employee table, and the salary is also 1000

    1. con2 = getConnection();     2. Insert into employee(empId,salary) values("Lili",1000);     3. con2.commit();

    Transaction 1 reads all employees whose salaries are 1000 again

    1. //con1     2. select * from employee where salary =1000;

    A total of 11 records were read, which produced phantom reading.
    Isolation_serializable can avoid this situation. However, this consumes the most resources.

    Getpropagationbehavior ()Returns the Propagation Behavior of a transaction. It is determined by whether there is an active transaction.

    The transactiondefinition interface defines seven transaction propagation behaviors..

    Propagation_requiredIf a transaction exists, the current transaction is supported. If no transaction exists, a new transaction is started.

    1. // transaction property propagation_required 2. methoda {3 ....... 4. methodb (); 5 ....... 6.}. // transaction property propagation_required 9. methodb {10 ....... 11 .}

    With Spring declarative transactions, spring uses AOP to support declarative transactions. Based on the transaction attributes, it automatically determines whether to enable a transaction before calling the method, after the method is executed, the transaction is committed or rolled back.

    Call the methodb method separately

    1. main{     2.   metodB();     3. }

    Equivalent

    1. main {2. connection con = NULL; 3. 4. rry {5. con = getconnection (); 6. con. setautocommit (false); 7. // method call 8. methodb (); 9. // submit the transaction 10. con. commit (); 11 .} 12. catch (runtimeexception ex) {13. // roll back the transaction 14. con. rollback (); 15 .} 16. finally {17. // release resources 18. closecon (); 19 .} 20 .}

    Spring ensures that all calls in the methodb method get the same connection. When methodb is called, there is no transaction, so a new connection is obtained and a new transaction is started.

    When you call methoda separately, methodb is called again in methoda.

    The execution effect is equivalent

    1. main{     2.    Connection con = null;     3.    try{     4.       con = getConnection();     5.       methodA();     6.       con.commit();     7. }     8. cathc(RuntimeException ex){     9.  con.rollback();    10. }    11. finally{    12.   closeCon();    13. }     14. }

    When methoda is called, there is no transaction in the environment, so a new transaction is started.
    When methodb is called in methoda, there is already a transaction in the environment, so methodb joins the current transaction.

    Propagation_supportsIf a transaction exists, the current transaction is supported. If no transaction exists, the transaction is not executed. However, for the transaction manager for transaction synchronization, propagation_supports is slightly different from not using transactions.

    1. // transaction property propagation_required 2. methoda () {3. methodb (); 4 .} 5. 6. // transaction property propagation_supports 7. methodb () {8. ...... 9 .}

    When you call methodb, The methodb method is not executed by a transaction.
    When methda is called, methodb is added to the methoda transaction for transaction execution.

    Propagation_mandatory if a transaction already exists, the current transaction is supported. If no active transaction exists, an exception is thrown.

    1. // transaction property propagation_required 2. methoda () {3. methodb (); 4 .} 5. 6. // transaction property propagation_mandatory 7. methodb () {8. ...... 9 .}

    When methodb is called separately, an exception is thrown because there is no active transaction currently.
    Throw new illegaltransactionstateexception ("transaction propagation 'mandatory 'but no existing transaction found ");

    When methoda is called, methodb is added to the methoda transaction for transaction execution.

    Propagation_requires_newAlways start a new transaction. If a transaction already exists, the transaction will be suspended.

    1. // transaction property propagation_required 2. methoda () {3. dosomethinga (); 4. methodb (); 5. dosomethingb (); 6 .} 7. 8. // transaction property propagation_requires_new 9. methodb () {10. ...... 11 .}

    When you call methodb separately, it is equivalent to declaring methodb as required. Start a new transaction and execute the transaction.

    When methoda is called

    1. main(){     2.   methodA();     3. }

    The situation is quite different. It is equivalent to the following effect.

    1. main () {2. transactionmanager TM = NULL; 3. try {4. // obtain a JTA Transaction Manager. TM = gettransactionmanager (); 6. TM. begin (); // start a new transaction. transaction ts1 = TM. gettransaction (); 8. dosomething (); 9. TM. suspend (); // suspends the current transaction 10. try {11. TM. begin (); // restart the second transaction 12. transaction ts2 = TM. gettransaction (); 13. methodb (); 14. ts2.commit (); // submit the second transaction 15. 16 .} 17. catch (runtimeexception ex) {18. ts2.rollback (); // roll back the second transaction 19 .} 20. finally {21. // release the resource 22 .} 23. // restore the first transaction 24 after executing methodb. TM. resume (ts1); 25. dosomethingb (); 26. ts1.commit (); // submit the first transaction 27 .} 28. catch (runtimeexception ex) {29. ts1.rollback (); // roll back the first transaction 30 .} 31. finally {32. // release resource 33 .} 34 .}

    Here, ts1 is called an outer transaction and ts2 is called an internal transaction. The code above shows that ts2 and ts1. Whether ts2 is successful or not depends on ts1. If the dosomethingb method fails after the methodb method is called, the results of the methodb method are still submitted. The results caused by other Code except methodb are rolled back.
    To use propagation_requires_new, use jtatransactionmanager as the Transaction Manager.

    Propagation_not_supportedAlways executes non-transactions and suspends any existing transactions.

    1. // transaction property propagation_required 2. methoda () {3. dosomethinga (); 4. methodb (); 5. dosomethingb (); 6 .} 7. 8. // transaction attribute propagation_not_supported 9. methodb () {10. ...... 11 .}

    When methodb is called separately, no transaction mechanism is enabled for non-transaction execution.
    When methoda is called, it is equivalent to the following effect:

    1. main () {2. transactionmanager TM = NULL; 3. try {4. // obtain a JTA Transaction Manager. TM = gettransactionmanager (); 6. TM. begin (); // start a new transaction. transaction ts1 = TM. gettransaction (); 8. dosomething (); 9. TM. suspend (); // suspends the current transaction 10. methodb (); 11. // restore the first transaction 12 after executing methodb. TM. resume (ts1); 13. dosomethingb (); 14. ts1.commit (); // submit the first transaction 15 .} 16. catch (runtimeexception ex) {17. ts1.rollback (); // roll back the first transaction 18 .} 19. finally {20. // release resource 21 .} 22 .}

    To use propagation_not_supported, you also need to use jtatransactionmanager as the Transaction Manager.

    Propagation_neverAlways executes non-transactional operations. If an active transaction exists, an exception is thrown.

    # // Transaction attribute propagation_required # methoda () {# dosomethinga (); # methodb () ;# dosomethingb () ;###// transaction attribute propagation_never # methodb () {#...... #}

    If you call methodb separately, the transaction is not executed.
    If you call methoda, an exception is thrown.
    Throw new illegaltransactionstateexception (
    "Transaction propagation 'never 'but existing transaction found ");

    Propagation_nestedIf an active transaction exists, it runs in a nested transaction. If no active transaction exists, it is executed according to the transactiondefinition. propagation_required attribute.

    This is a nested transaction. When the JDBC 3.0 driver is used, only cetcetransactionmanager is supported as the Transaction Manager. Java. SQL. savepoint class that requires a JDBC driver. Some JTA Transaction Manager implementations may also provide the same functionality.

    When propagation_nested is used, you also need to set the nestedtransactionallowed attribute of platformtransactionmanager to true;
    The default value of nestedtransactionallowed is false;

    1. // transaction property propagation_required 2. methoda () {3. dosomethinga (); 4. methodb (); 5. dosomethingb (); 6 .} 7. 8. // transaction property propagation_nested 9. methodb () {10. ...... 11 .}

     
    If the methodb method is called separately, it is executed according to the required attribute.

    If you call the methoda method, it is equivalent to the following effect:

    1. main () {2. connection con = NULL; 3. savepoint = NULL; 4. try {5. con = getconnection (); 6. con. setautocommit (false); 7. dosomethinga (); 8. savepoint = con2.setsavepoint (); 9. try 10. methodb (); 11 .} catch (runtimeexception ex) {12. con. rollback (savepoint); 13 .} 14. finally {15. // release resource 16 .} 17. 18. dosomethingb (); 19. con. commit (); 20 .} 21. catch (runtimeexception ex) {22. con. rollback (); 23 .} 24. finally {25. // release resource 26 .} 27 .}

    Before the methodb method is called, call the setsavepoint method to save the current status to savepoint. If the methodb method fails to be called, it is restored to the previously saved state. However, the transaction is not committed at this time. If the subsequent code (dosomethingb () method) fails to be called, the rollback includes all operations of the methodb method.

    An important concept of nested transactions is that the inner transaction depends on the outer transaction. When an outer transaction fails, the action performed by the internal transaction is rolled back. The failure of the internal transaction does not cause the rollback of the outer transaction..

    Difference between propagation_nested and propagation_requires_new: They are very similar, like a nested transaction. If there is no active transaction, a new transaction will be started. When propagation_requires_new is used, the internal transaction and the outer transaction are like two independent transactions. Once the internal transaction is committed, the outer transaction cannot roll back it. Two transactions do not affect each other. Two transactions are not a real nested transaction. It also requires support from the JTA Transaction Manager.
    When propagation_nested is used, the rollback of the outer transaction can cause the rollback of the inner transaction. The exception of the internal transaction does not cause the rollback of the outer transaction. It is a real nested transaction. When datasourcetransactionmanager uses savepoint to support propagation_nested, JDBC 3.0 and later drivers and JDK 1.4 and later versions are required. Other JTA trasactionmanager implementations may have different support methods.

    Propagation_required should be our first transaction Propagation Behavior. It can meet most of our transaction needs.

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.