Distributed Transaction Series (1.1) Spring transaction manager Platformtransactionmanager

Source: Internet
Author: User
Tags savepoint try catch

1 Series Catalogue
    • The Distributed Transaction series (opening) raises questions and research processes
    • Distributed Transaction Series (1.1) Spring transaction manager Platformtransactionmanager Source analysis
2 JDBC Transaction2.1 Examples
public void save(User user) throws SQLException{    Connection conn=jdbcDao.getConnection();    conn.setAutoCommit(false);    try {       PreparedStatement ps=conn.prepareStatement("insert into user(name,age) value(?,?)");       ps.setString(1,user.getName());       ps.setInt(2,user.getAge());       ps.execute();       conn.commit();    } catch (Exception e) {       e.printStackTrace();       conn.rollback();    }finally{       conn.close();    }}
2.2 Analysis
    • How to use Transactions

      Set Autocommit to False, which is Conn.setautocommit (false), and then manually to Conn.commit (), or conn.rollback ().

    • An important consciousness

      Conn.commit (); Conn.rollback () These are transaction codes, other code that executes SQL belongs to the business code

      Only when the transaction code and the business code use the same connection, the rollback and the commit of the transaction can execute properly, so if we are to implement the separation of the transaction code and the business code, we must ensure that they are using the same connection.

    • Who is performing the transaction

      As we can see, the transaction can be performed by manipulating the connection connection, which does not mean that connection has a transactional function, but rather uses the transaction function of the database itself, connection only to pass some commands such as commit, rollback to the database

2.3 Problems that exist
    • 1 business code is nested in the Try Catch transaction template code
    • 2 when there are multiple business logic like save (user user), there is no guarantee that their atomicity

      login(user);save(user);

      Both of these business logic are similar code, get the connection connection, and then execute the SQL statement. There is no guarantee that they are atomic because they are not using the same connection, not within the same transaction.

3 Hibernate's Business3.1 Examples
public void save(User user){    Session session=hibernateDao.openSession();    Transaction tx=null;    try {       tx=session.beginTransaction();          session.save(user);          tx.commit();      } catch (Exception e) {       if(tx!=null){         tx.rollback();       }    }finally{       session.close();    }}
3.2 Analysis
    • Separation of transaction functions and business functions

      In a JDBC transaction, connection burdens two aspects of functionality, transactional functionality, and the ability to execute SQL. The transaction here is Hibernate's own definition of the transaction, Hibernate is the function of the two separate, the transaction function to the transaction, make the responsibility more clear division of labor.

    • The principle of the transaction

      In fact, the session, transaction internal will have a same connection, so that the business code and transaction code to use the same connection, The rollback of the transaction transaction is done by the internal connection, as follows:

      • Start of transaction, set Autocommit to False

      • Commit of the transaction, submitted by connection's Commit method

      Operations such as rollback of transactions, no longer enumerated

4 The overall interface design of spring transaction function

Because of the different ways in which the transaction functions are implemented, spring has a unified abstraction that forms the Platformtransactionmanager transaction manager interface, and the commit, rollback, etc. of the transaction are all given to it. Spring's transaction system is also carried out on the Platformtransactionmanager transaction manager interface, so first understand the next Platformtransactionmanager transaction manager.

4.1 Overall interface design for transactional functions

Let's take a look at the three main interfaces

    • Platformtransactionmanager: Transaction manager

    • Transactiondefinition: Some basic information about a transaction, such as time-outs, isolation levels, propagation properties, and so on

    • Transactionstatus: Some state information for a transaction, such as whether it is a new transaction, whether it has been marked as rollback

Take a look at how Platformtransactionmanager operates the transaction:

public interface PlatformTransactionManager {    //根据事务定义TransactionDefinition,获取事务    TransactionStatus getTransaction(TransactionDefinition definition);    //提交事务    void commit(TransactionStatus status);    //回滚事务    void rollback(TransactionStatus status);}
4.2 Interface corresponding to the implementation4.2.1 Transaction Definition Interface Transactiondefinition

    • Above the red line are some constant definitions (the isolation level of the transaction and the propagation properties of the transaction, specifically no longer say, a whole bunch of online)
    • The definition of a transaction consists of the isolation level of the transaction, the propagation property of the transaction, the time-out setting, whether it is read-only

To understand the place:

The isolation level of a transaction is the transaction capability of the database itself, but the propagation properties of a transaction are the features that spring itself provides for us, and the notion that a database transaction does not have a transactional propagate property.

Implementation of the interface Defaulttransactiondefinition: the default transaction definition

public class DefaultTransactionDefinition implements TransactionDefinition, Serializable {    private int propagationBehavior = PROPAGATION_REQUIRED;    private int isolationLevel = ISOLATION_DEFAULT;    private int timeout = TIMEOUT_DEFAULT;    private boolean readOnly = false;    //略}
    • The propagation property of a transaction is propagation_required, that is, when there is no transaction at present, create one, if any, using the current transaction
    • The isolation level of the transaction is based on the default isolation level of the underlying database
    • The timeout takes the default time-out for the underlying database
    • is read-only as false
4.2.2 Transaction Interface Definition Transactionstatus

The Save Points feature in the connection connection is first drawn:

//创建一个保存点conn.setSavepoint(name);//回滚到某个保存点conn.rollback(savepoint);//释放某个保存点conn.releaseSavepoint(savepoint);

Transactionstatus it inherits the Savepointmanager interface, Savepointmanager is the encapsulation of the above savepoint function in the transaction, as follows:

public interface SavepointManager {    Object createSavepoint() throws TransactionException;    void rollbackToSavepoint(Object savepoint) throws TransactionException;    void releaseSavepoint(Object savepoint) throws TransactionException;}

Spring uses the SavePoint feature to implement nested functions of transactions. Details are explained later.

The transactionstatus itself is more stored with some state information about the transaction:

    • Whether it's a new thing
    • Do you have a savepoint?
    • Whether it has been marked as rollback

The common Transactionstatus interface is implemented as Defaulttransactionstatus:

The JDBC transaction is currently implemented through connection, and Hibernate is implemented by its own definition of transaction, so the transactions are different for each family, so spring can only use object Transaction in the form of a transaction, the rollback and the submission of the transaction are ultimately delegated to the object transaction above.

The role of Object transaction is to commit a ROLLBACK transaction, and this transaction choice might look like this:

    • Datasourcetransactionobject
    • Hibernatetransactionobject
    • Jpatransactionobject (later in detail)

The details were as follows:

    • For Datasourcetransactionobject:

      We used the DataSource to get the connection, and to implement the transaction function, it was necessary to use connection, so there must be a connection in it to perform the operation of the transaction.

      There is a connectionholder in Datasourcetransactionobject, which encapsulates a connection.

    • For Hibernatetransactionobject:

      We use Hibenrate, which is what we need to do with Hibernate's own defined transaction to implement transactional functionality.

      Hibernatetransactionobject contains a sessionholder, like the above Connectionholder, it encapsulates a session, with a session, We can use the session to generate a hibernate transaction for transactional operations.

4.2.3 Transaction manager Interface Definition Platformtransactionmanager

The class diagram relationships are as follows:

The point is,

    • Abstractplatformtransactionmanager
      • Datasourcetransactionmanager
      • Hibernatetransactionmanager
      • Jpatransactionmanager (later in detail)

This needs to look at the interface of the transaction manager, and how they are implemented:

    • 1 First interface: transactionstatus gettransaction (transactiondefinition definition) Get transaction status based on transaction definition

      The general content is the first to obtain the above description of the object transaction, to determine whether the current transaction is already present, if there is a transaction propagation property processing, after the detailed explanation, if there is no new defaulttransactionstatus, the newly created a transaction, Use object transaction to open the transaction at the same time. The
      is divided into several procedures:

      • 1.1 Gets the object transaction:
        different transaction managers get different object Transaction-datasourcetransactionmanager is to get the above Datasourcetransactionobject Gets the connectionholder of the binding from the current thread, possibly NULL, and if NULL, takes a connection from the DataSource in the next open transaction, encapsulates the Connectionholder, Then bind to the current thread and then we new a datasourcetransactionobject, the concrete process is as follows:! [Datasourcetransactionmanager gets a transaction] [7]-Hibernatetransactionmanager gets hibernatetransactionobject from the current thread to get the sessionholder of the binding, possibly NULL, if NULL, A session is taken from Sessionfactory in the next open transaction, then encapsulated into Sessionholder, then bound to the current thread, and then we can get a new hibernatetransactionobject. , the specific process is as follows:! [Hibernatetransactionmanager gets a transaction] [8]  
-1.2 build Defaulttransactionstatus, use object transaction to open transaction-Datasourcetransactionmanager DATASOURCETRANSACTIONOBJEC The opening process is as follows: first to determine whether the previous fetch of the current thread-bound connectionholder is null, if NULL, to obtain a connection from DataSource, encapsulated as Connectionholder, Then bind to the current thread because a transaction is turned on, you must turn off autocommit connection in Datasourcetransactionobject, and the code is as follows (omitted): protected void Dobegin (Ob ject transaction, transactiondefinition definition) {datasourcetransactionobject Txobject = (datasourcetransacti          Onobject) transaction;          Connection con = null;                 If Connectionholder is null, obtain the new if (txobject.getconnectionholder () = = NULL | | Txobject.getconnectionholder (). Issynchronizedwithtransaction ()) {Connection Newcon = This.dataSource.getConn              Ection ();          Txobject.setconnectionholder (New Connectionholder (Newcon), true);          } con = Txobject.getconnectionholder (). getconnection (); Integer Previousisolationlevel = Datasourceutils.prepareconnectIonfortransaction (con, definition);          Txobject.setpreviousisolationlevel (Previousisolationlevel);              Cancels autocommit if (Con.getautocommit ()) {Txobject.setmustrestoreautocommit (true);              if (logger.isdebugenabled ()) {Logger.debug ("Switching JDBC Connection [" + con + "] to Manual commit");          } con.setautocommit (FALSE);          } txobject.getconnectionholder (). Settransactionactive (True); If it is a new connectionholder, bind to the current thread if (Txobject.isnewconnectionholder ()) {transactionsynchronization          Manager.bindresource (Getdatasource (), Txobject.getconnectionholder ()); }}-The hibernatetransactionobject of Hibernatetransactionmanager is opened as follows: The same logic, if Sessionholder is null, from Sessi  Onfactory gets a session, then encapsulates it into Sessionholder, then binds the sessionholder to the current thread session NewSession = (Entityinterceptor! = null              ? Getsessionfactory (). Withoptions (). Interceptor (ENTItyinterceptor). Opensession (): Getsessionfactory (). Opensession ());       Txobject.setsession (newsession);         At the same time, using the session above to open a transaction, the transaction object is also saved to the above Sessionholder.         Transaction hibtx=session.begintransaction ();       Txobject.getsessionholder (). Settransaction (HIBTX);         If it is a newly created sessionholder, bind to the current thread/bind the session holder to the thread. if (Txobject.isnewsessionholder ()) {Transactionsynchronizationmanager.bindresource (Getsessionfactory (), TxObject         . Getsessionholder ()); }
  • 2 Second interface: void rollback (transactionstatus status) roll back a transaction

    Rollback, or use an object transaction inside Defaulttransactionstatus to perform a rollback operation

      • Datasourcetransactionmanager is a rollback operation using the connection in the Datasourcetransactionobject
        protected void doRollback(DefaultTransactionStatus status) {       DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();       Connection con = txObject.getConnectionHolder().getConnection();       try {         con.rollback();       }       catch (SQLException ex) {         throw new TransactionSystemException("Could not roll back JDBC transaction", ex);       }    }
      • Hibernatetransactionmanager is a transaction transaction created using the session in the Sessionholder in hibernatetransactionobject to roll back the operation
        protected void doRollback(DefaultTransactionStatus status) {       HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();       try {         txObject.getSessionHolder().getTransaction().rollback();       }    }
  • 3 Third interface: void commit (Transactionstatus status) COMMIT Transaction

    Similarly, Datasourcetransactionmanager relies on internal connection to complete the commit operation

    Hibernatetransactionmanager relies on internal transaction to complete the commit operation

Analysis of propagation properties of 4.3 transactions

You can refer to the case of this article to illustrate the propagation behavior and isolation level of spring transactions, the following key source analysis under the spring's transaction propagation properties:

The code for the propagation properties of a transaction is as follows:

After the object transaction is obtained, it is determined whether it is an existing transaction. Because the acquisition of this object transaction is obtained directly from the thread binding, it is possible that when a transaction already exists on the front-line, it is determined as follows:

    • Datasourcetransactionmanager

      protected boolean isExistingTransaction(Object transaction) {    DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;    return (txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive());}

      Is whether a transaction already exists in the Connectionholder bound by the current thread

    • Hibernatetransactionmanager

      public boolean hasSpringManagedTransaction() {    return (this.sessionHolder != null && this.sessionHolder.getTransaction() != null);}

      is also a transaction based on whether the Sessionholder is bound to the current thread

If a transaction is already present: the propagation property of the transaction needs to be processed, as in the Handleexistingtransaction method described above:

  • 1 Propagation_never: A transaction is not allowed, if a thrown exception is present

    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {    throw new IllegalTransactionStateException(         "Existing transaction found for transaction marked with propagation ‘never‘");}
  • 2 propagation_not_supported: Transaction is not supported, if a transaction is present, the transaction must be suspended, saved, and the pending transaction needs to resume after execution is complete

    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {    if (debugEnabled) {       logger.debug("Suspending current transaction");    }    Object suspendedResources = suspend(transaction);    boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);    return prepareTransactionStatus(         definition, null, false, newSynchronization, debugEnabled, suspendedResources);}

    After suspending, an object Transaction=null transaction is generated, that is, the transaction code is not executed, and the suspended resource information is passed to the newly created transaction, and when the transaction is completed, the suspended resources are restored.

      • 2.1 For Datasourcetransactionmanager, the suspend of a transaction is to unbind the Connectionholder associated with the current thread:
        protected Object doSuspend(Object transaction) {       DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;       txObject.setConnectionHolder(null);       ConnectionHolder conHolder = (ConnectionHolder)          TransactionSynchronizationManager.unbindResource(this.dataSource);       return conHolder;    }同理事务的恢复就是把上述ConnectionHolder再重新绑定到当前线程,继续执行该事务
      • 2.2 For Hibernatetransactionmanager, the suspend of a transaction is to unbind the Sessionholder associated with the current thread
      Protected Object Dosuspend (object transaction) {Hibernatetransactionobject Txobject = (Hibernatetran       Sactionobject) transaction;       Txobject.setsessionholder (NULL); Sessionholder Sessionholder = (sessionholder) transactionsynchronizationmanager.unbindresource (GetSessionFactory (       ));       Txobject.setconnectionholder (NULL);       Connectionholder connectionholder = null; if (getdatasource () = null) {Connectionholder = (Connectionholder) Transactionsynchronizationmanager.unbindresou       Rce (Getdatasource ());    } return new Suspendedresourcesholder (Sessionholder, Connectionholder); The recovery of the same transaction is to re-bind the above sessionholder to the current thread and proceed with the transaction  
  • 3 propagation_requires_new: Opens a new transaction and hangs the current transaction if the current transaction is present

      if (definition.getpropagationbehavior () = = transactiondefinition.propagation_requires_new) {Suspendedresourcesholder suspendedresources = suspend (    Transaction);       try {Boolean newsynchronization = (Gettransactionsynchronization ()! = Synchronization_never); Defaulttransactionstatus status = Newtransactionstatus (definition, transaction, True, Newsynchronization, Debuge       Nabled, suspendedresources);       Dobegin (transaction, definition);       Preparesynchronization (status, definition);    return status; }}  
    you can see that creating a new transaction invokes Dobegin (transaction, definition), and the transaction is opened.
  • 4 propagation_nested: Principle Many people have explained in detail, can refer to a simple understanding of spring in the propagation_nested, source confirmation to continue to study

    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {    if (useSavepointForNestedTransaction()) {       DefaultTransactionStatus status =          prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);       status.createAndHoldSavepoint();       return status;    }}

    This uses the object transaction to create the savepoint, still using the original transaction

  • 5 Propagation_supports and propagation_required: If a transaction is currently present, the thing is still used

At this point the transaction manager interface is simply finished, there are a lot of details of things, you need to study carefully.

5 concluding remarks

Understanding the Platformtransactionmanager transaction Manager, the following is the implementation of spring's programmatic transactions, declarative transactions, so the next article reads as follows:

    • Transactiontemplate can implement programmatic transactions
    • Spring uses AOP to implement declarative transactions

Distributed Transaction Series (1.1) Spring transaction manager Platformtransactionmanager

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.