Managing transactional and propagation behavior with spring annotations

Source: Internet
Author: User
Tags savepoint

Managing transactions with spring annotations

The previous explanation of how to use the @transactional annotation declaration Personservicebean all the business methods under the need of transaction management, then how to manage the transaction?
We know that when each business method executes, it opens the transaction, and after the execution of the business method finishes, it ends the transaction. So when does it decide to commit the transaction and when does it decide to rollback the transaction? When we were manually controlling the transaction, the commit or rollback of the transaction was usually manipulated by us, and now we are using the container's declarative transaction management, how do we know when the transaction is committed and when to roll back? The answer is that the spring container defaults to a run-time exception, and it rolls back the transaction, and if it encounters a user exception, such as a check-in exception (checked exception), then the transaction is not rolled back.
Now we're going to do an experiment. Suppose the person table has the following records:

If we want to delete the record with ID 5 in the person table now, but in the delete () method of the Personservicebean class, a runtime exception is thrown artificially, as follows:

public void delete(Integer personid) {    jdbcTemplate.update("delete from person where id=?", new Object[]{personid}, new int[]{java.sql.Types.INTEGER}); throw new RuntimeException("运行期异常");}

Now test the Delete () method in the Personservicetest class:

@Testpublic void delete() {    personService.delete(5);}

The Eclipse console prints an exception and immediately looks at the person table and finds that the record with ID 5 is not deleted, which means that the spring container defaults to the runtime exception and it rolls back the transaction .
If in the Delete () method of the Personservicebean class, a check-in exception is thrown artificially, as follows:

public void delete(Integer personid) throws Exception {    jdbcTemplate.update("delete from person where id=?", new Object[]{personid}, new int[]{java.sql.Types.INTEGER}); throw new Exception("检查时异常");}
    • 1

In order not to give an error, we must also modify the Delete () method signature in the Personservice interface to:

/** * 删除指定id的person */public void delete(Integer personid) throws Exception;

Now test the Delete () method in the Personservicetest class:

@Testpublic void delete() {    try { personService.delete(5); } catch (Exception e) { e.printStackTrace(); }}

The Eclipse console prints an exception and immediately looks at the person table and finds that the record with ID 5 is deleted, which means that if the spring container encounters a user exception, such as an exception on check (checked exception), the transaction will not be rolled back .
Of course we can also change this rule:

  • Let the transaction roll back when the spring container encounters a user exception-such as an exception when checking (checked exception).
    What the hell is that supposed to do? You need to use the Rollbackfor property of the transaction at this point. We modify the Delete () method of the Personservicebean class to:

    @Transactional(rollbackFor=Exception.class)public void delete(Integer personid) throws Exception { jdbcTemplate.update("delete from person where id=?", new Object[]{personid}, new int[]{java.sql.Types.INTEGER}); throw new Exception("检查时异常");}
      • 1

    Now test the Delete () method in the Personservicetest class:

    @Testpublic void delete() {    try { personService.delete(4); } catch (Exception e) { e.printStackTrace(); }}
      • 1

    You will see that the Eclipse console prints an exception and immediately looks at the person table and finds that the record with ID 4 has not been deleted.

  • When a spring container encounters a run-time exception, it does not let the transaction roll back, but commits the transaction.
    What the hell is that supposed to do? You need to use the Rollbackfor property of the transaction at this point. We modify the Delete () method of the Personservicebean class to:

    @Transactional(noRollbackFor=RuntimeException.class)public void delete(Integer personid) throws Exception { jdbcTemplate.update("delete from person where id=?", new Object[]{personid}, new int[]{java.sql.Types.INTEGER}); throw new RuntimeException("运行期异常");}
      • 1

    When you test the Delete () method in the Personservicetest class, you see that the Eclipse console prints an exception and immediately looks at the person table and finds that the record with ID 4 has been deleted.

Transaction propagation Properties

Transactions also have some other characteristics, such as in the business Bean--personservicebean, some business methods do not need transaction management, such as the method of acquiring data, then we need to use the propagation property of things, This property specifies the propagation behavior of the transaction. Therefore, we should modify the code of the Getperson () method to:

/** * 使用JdbcTemplate获取一条记录 */@Transactional(propagation=Propagation.NOT_SUPPORTED)public Person getPerson(Integer personid) {    return jdbcTemplate.queryForObject("select * from person where id=?", new Object[]{personid}, new int[]{java.sql.Types.INTEGER}, new PeronRowMapper());}
    • 1

Also modify the code of the Getpersons () method to:

/** * 使用JdbcTemplate获取多条记录 */@Transactional(propagation=Propagation.NOT_SUPPORTED)public List<Person> getPersons() {    return jdbcTemplate.query("select * from person", new PeronRowMapper());}
    • 1

In this way, when the 2 business methods are executed, it will not open transactions, save resources and provide efficiency.
Let's take a summary of the transaction propagation properties:

  • REQUIRED: The business method needs to run in a transaction. If the method is already in a transaction while it is running, it will be added to the transaction, and if there is no current transaction environment, a new transaction will be created for itself. By default, the transaction propagation property of a business method is required. In application development, this transaction propagation property is used in 80% of the cases.
  • Not_supported: Declaring a method does not require a transaction. If the method is not associated to a transaction, the container does not open the transaction for it. If the method is called in a transaction (called in a method of another business bean, and the method of the other business bean is open for the transaction), the transaction is suspended and the original transaction resumes execution after the method call ends.
  • RequiresNew: This property indicates that the business method always initiates a new transaction for itself, regardless of whether a transaction is currently present. If the method is already running in a transaction, the original transaction is suspended, the new transaction is created, and the new transaction is completed until the method executes, and the original transaction resumes execution.
  • MANDATORY: This property specifies that the business method can only be executed in a transaction that already exists, and the business method cannot initiate its own transaction. If the business method is called in an environment without transactions, the container throws an exception.
  • SUPPORTS: This transaction property indicates that if a business method is called within a transaction scope, the method becomes part of the transaction. If the business method is called outside the scope of the transaction, the method executes in an environment without transactions. That is, when the business method that labels the transaction propagation property--supports is executed in the business method of another bean, if the business method of the other bean opens the transaction, then it executes in the transaction when the business method that annotated the transaction propagation property--supports is executed. If the business method of another bean does not open the transaction, then the business method labeled Transaction propagation Property--supports is also in an environment where there is no transaction .
  • Never: Specifies that the business method must never be executed within the scope of the transaction. If the business method executes in a transaction, the container throws an exception, and only the business method is not associated to any transaction for normal execution.
  • NESTED: If an active transaction exists, the current method runs in a nested transaction. If there is no active transaction, it is performed by the required property. It uses a separate transaction that has multiple savepoint that can be rolled back. The rollback of internal transactions does not affect external transactions. It only works on the Datasourcetransactionmanager transaction manager.

Next, we focus on transaction propagation property--nested. If you have the following code:

@Resource OtherService otherService;public void xxx() {    stmt.executeUpdate("update person set name=‘888‘ where id=1"); otherService.update(); // OtherService的update()方法的事务传播属性为NESTED stmt.executeUpdate("delete from person where id=9");}
    • 1

Expanding the code above may turn out to be a piece of code like this:

Connection conn =Nulltry {conn.setautocommit (FALSE);    Statement stmt = Conn.createstatement (); Stmt.executeupdate ( "update person set name= ' 888 ' where id=1"); SavePoint savepoint = Conn.setsavepoint (); //save point try{conn.createstatement (). Executeupdate ( "update person set name= ' 222 ' where sid=2"); }catch (exception ex) {conn.rollback (savepoint);} Stmt.executeupdate ( "delete from person where id=9"); Conn.commit (); Stmt.close ();} catch (exception e) {conn.rollback ();} finally{try {if (null!=conn &&!conn.isclosed ()) conn.close (); } catch (SQLException e) {e.printstacktrace ();}}       
    • 1

The update () method, which otherservice the transaction propagation property to nested, is equivalent to a piece of code:

// 保存点try{       conn.createStatement().executeUpdate("update person set name=‘222‘ where sid=2");}catch(Exception ex){ conn.rollback(savepoint); }
    • 1

We also understand that the rollback of internal transactions does not affect external transactions.

Other properties of a transaction

In addition to transactional propagation properties, transactions have some other properties:

    • ReadOnly Property: Set to read-only transaction, for read-only transactions, it can not be updated operation, generally only exist when the data read, the ReadOnly property may be set to true, can provide efficiency.
    • Timeout property: Represents the time-out period for a transaction, which defaults to 30s, and generally does not require setting a time-out.
Isolation property of a transaction

The isolation property of a transaction specifies the isolation level of the transaction, in fact the isolation level of the transaction is not determined by the spring container, but is determined by the underlying database.

Database system provides four types of transaction isolation levels

The database system provides four levels of transaction isolation for users to choose from. Different isolation levels are implemented with different lock types, with the highest isolation level of serializable in four isolation levels, but with the greatest impact on the performance of concurrent Access databases. Read uncommited has the lowest isolation level. The default isolation level for most databases is read commited, such as SQL Server, and of course there are a few databases with a default isolation level of repeatable read, such as MySQL.

    • Read uncommited: Reading uncommitted data (dirty reads, non-repeatable reads, and Phantom reads)
    • Read commited: Reading committed data (non-repeatable read and Phantom reads occur)
    • REPEATABLE READ: Repeatable reading (phantom reading will occur)
    • Serializable: Serialization

Dirty reads : One transaction reads to another transaction uncommitted update new data. The premise is that two or more transactions are concurrent.
non-repeatable read : In the same transaction, multiple reads of the same data return different results. In other words, a subsequent read can read the updated data that was committed by another transaction. Conversely, " repeatable read " can guarantee the same read data when it is read more than once in the same transaction, that is, subsequent reads cannot be read to the updated data submitted by another transaction. At present, to achieve repeatable reading, the general database uses snapshot technology, in a moment (point), when you access the data, it takes this data as a mirror, and later in the same transaction to read the same record data, it can be returned from the snapshot of the data, No matter how it operates on the outside, it will not be affected when it is read multiple times.
Phantom Read : One transaction reads the insert data that has been committed by another transaction.

Managing transactional and propagation behavior with spring annotations

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.