JdbcTemplate manual control of transactions when Autocommit is true

Source: Internet
Author: User

This is the work of a real problem encountered in the processing process, if the analysis process is not interested, you can skip to the final view of the final plan.

We are not using any ORM framework (either Hibernate or MyBatis, or dbutils) in the persistence layer, but instead use a simple wrapper on the jdbctemplate basis, We also decided to set autocommit to true to commit immediately after the SQL statement execution is complete. This is better and more convenient than @transactional annotations or using AOP to control transactional performance.

After evaluating the pros and cons, we begin to use this approach, and we also have a real problem with it. Here we have all the information about the company is hidden, the simplified requirement is: a business to execute two consecutive table insert operation, must be guaranteed to take effect or failure. Of course, the use of compensation can also achieve the effect, but considering that our user volume is not very large, and in the future for a period of time the user will not increase, the use of compensation a little outweigh the benefits, so decided to use the manual control of the transaction under certain circumstances, the rest of the default autocommit is true. After setting this goal, we begin to study if it is done on a jdbctemplate basis.

The first thing to try is to get connection, and set Autocommit to False, the code is as follows:

DataSource DataSource = ((JdbcTemplate) namedparameterjdbctemplate.getjdbcoperations ()). Getdatasource (); Connection Connection = datasourceutils.getconnection (DataSource); Connection.setautocommit (false);

After Setup, the test discovery does not take effect, and it is already known that this is useless. Next we further analyze how to get the database connection in JdbcTemplate, can be viewed by breaking point, each connection object hashcode inconsistent.


We know that namedparameterjdbctemplate This class holds an example of JdbcTemplate , and we're from Namedparameterjdbctemplate 's The update method follows the layers and finds that the following method of the JdbcTemplate class is finally called:

protected int Update (final PreparedStatementCreator psc, Final PreparedStatementSetter pss) throws Dataaccessexceptio N

This method also calls the following method:

Public <T> T Execute (PreparedStatementCreator psc, preparedstatementcallback<t> action) throws DataAccess Exception

In this execute method we find the way JdbcTemplate obtains a database connection, namely:

Connection con = datasourceutils.getconnection (Getdatasource ());

Continue to trace in, found that the final call is datasourceutils the following method:

Public static connection dogetconnection (Datasource datasource)  throws  Sqlexception {   assert.notnull (datasource,  "no datasource specified");    ConnectionHolder conHolder =  (Connectionholder)   Transactionsynchronizationmanager.getresource (DataSource);   if  (conholder !=  null &&  (conholder.hasconnection ()  | |  conholder.issynchronizedwithtransaction ()))  {       Conholder.requested ();      if  (!conholder.hasconnection ())  {          logger.debug ("Fetching resumed jdbc connection  from datasource ");          conholder.setconnection ( Datasource.getconnection ());       }      return  conholder.gEtconnection ();   }   // else we either got no  Holder or an empty thread-bound holder here.   logger.debug (" Fetching jdbc connection from datasource ");    connection con =  datasource.getconnection ();   if  ( Transactionsynchronizationmanager.issynchronizationactive ())  {       Logger.debug ("Registering transaction synchronization for jdbc connection");       // Use same Connection for further JDBC  actions within the transaction.      // thread-bound  Object will get removed by synchronization at transaction completion.       connectionholder holdertouse = conholder;      if  (holdertouse == null)  {          holdertouse = new connectionholder (Con);       }      else {          holdertouse.setconnection (Con);      }       Holdertouse.requested ();       Transactionsynchronizationmanager.registersynchronization (             new connectionsynchronization (Holdertouse, datasource));       holdertouse.setsynchronizedwithtransaction (true);       if   (Holdertouse != conholder)  {          Transactionsynchronizationmanager.bindresource (datasource, holdertouse); &nbsP;     }   }   return con;} 

Explain the above code: each time you get a database connection, it is first to determine whether Transactionsynchronizationmanager contains connectionholder, If it contains a straight return, if not included, first obtain a connection from DataSource and then process it in two cases:

When transactionsynchronizationmanager.issynchronizationactive () is true, the Connectionholder is initialized, and call Transactionsynchronizationmanager.bindresource (DataSource, Holdertouse) and complete the binding. As for the scope of the binding, we can see the definition of the variable in the Transacionsynchronizationmanager code.

private static final threadlocal<map<object, object>> resources =       new NamedThreadLocal<Map<Object, Object>> (" Transactional resources ");p rivate static final threadlocal<set< transactionsynchronization>> synchronizations =      new  Namedthreadlocal<set<transactionsynchronization>> ("Transaction synchronizations");p rivate  static final ThreadLocal<String> currentTransactionName =       new NamedThreadLocal<String> ("Current transaction name");p rivate  static final threadlocal<boolean> currenttransactionreadonly =       new NamedThreadLocal<Boolean> ("current transaction read-only  Status ");p Rivate static final threadlocal<integer> currenttransactionisolationlevel =      new  Namedthreadlocal<integer> ("Current transaction isolation level");p rivate static  final ThreadLocal<Boolean> actualTransactionActive =       new NamedThreadLocal<Boolean> ("actual transaction active");

Are threadlocal, that is, the effective range is within the current thread.

Two do not deal with Connectionholder, return directly to connection.


See here, we must know what to do, and then give us the final modification code (omit all the catch):

transactionsynchronizationmanager.initsynchronization ();D atasource  datasource =  ((JdbcTemplate) jdbctemplate.getjdbcoperations ()). Getdatasource (); Connection connection = datasourceutils.getconnection (DataSource);try {     connection.setautocommit (false);     //needs to manipulate two inserts of the database, or provide callbacks to business developers      connection.commit ();}  catch  (sqlexception e)  {} finally {    try {         transactionsynchronizationmanager.clearsynchronization ();     } catch  (illegalstateexception e)  {    }     try {        connection.setautocommit (True);     } catch  (Sqlexception e)  {    }} 

In conclusion , Spring's JdbcTemplate provides a wealth of operations that are not normally noticed. In the face of problems must not panic, careful analysis of logic, read the source code, I believe the problem will be resolved.











This article is from the "Valley Wind" blog, please be sure to keep this source http://1202955.blog.51cto.com/1192955/1926768

JdbcTemplate manual control of transactions when Autocommit is true

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.