`

spring 1.1.3 JDBC编程式事务管理探析(二):如何实现TransactionTemplate.execute的回调接口TransactionCal

 
阅读更多

 一、TransactionCallback接口

Object doInTransaction(TransactionStatus status)

TransactionTemplate已经搭好了事务框架,我们只需将多条SQL语句放在doInTransaction中执行就可以了。但是SQL语句通过什么方法来执行呢?

二、方法一:获取Connection来执行

获取Connection又有两种方法

1.从TransactionStatus中索得,因为TransactionStatus含有Transaction对象,后者保存了Connection的句柄

[Java] view plain copy
  1. private   static  Connection getConnection(TransactionStatus ts) {  
  2.   JdbcTransactionObjectSupport transObj = (JdbcTransactionObjectSupport)((DefaultTransactionStatus)ts).getTransaction();  
  3.   ConnectionHolder holder = transObj.getConnectionHolder();  
  4.   Connection con = holder.getConnection();  
  5.   return  con;  
  6. }  

2.从TransactionSynchronizationManager的线程变量中获取

[Java] view plain copy
  1. private  Connection getConnection() {  
  2.   DataSourceTransactionManager manager = (DataSourceTransactionManager)transactionTemplate.getTransactionManager();  
  3.   DataSource ds = manager.getDataSource();  
  4.   return  DataSourceUtils.getConnection(ds); //   
  5. }  
这里贴出DataSourceUtils.getConnection(ds)的部分代码:
[Java] view plain copy
  1. public   static  Connection getConnection(DataSource dataSource,  boolean  allowSynchronization)  
  2.   throws  CannotGetJdbcConnectionException {  
  3.   try  {  
  4.     return  doGetConnection(dataSource, allowSynchronization);  
  5.   }  
  6.   catch  (SQLException ex) {  
  7.     throw   new  CannotGetJdbcConnectionException( "Could not get JDBC connection" , ex);  
  8.   }  
  9. }  
  10.   
  11. protected   static  Connection doGetConnection(DataSource dataSource,  boolean  allowSynchronization)  
  12.   throws  SQLException {  
  13.   ...  
  14.   ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);  
  15.   if  (conHolder !=  null ) {  
  16.     return  conHolder.getConnection();  
  17.   }  
  18.   ...  
  19. }  

获取了Connection之后,就可以按照常规的方法来操作SQL语句了

[Java] view plain copy
  1. public   void  addEmployee1(Employee employee)  throws  SQLException {  
  2.   transactionTemplate.execute(new  TransactionCallback() {  
  3.     public  Object doInTransaction(TransactionStatus ts) {  
  4.       try  {  
  5.         //Connection con = getConnection(ts);   
  6.         Connection con = getConnection();  
  7.         Statement st = con.createStatement();  
  8.         st.executeUpdate("INSERT INTO Employee (username,age) VALUES('lizi', 22)" );  
  9.         st.executeUpdate("INSERT INTO Employee (username,age) VALUES('lijun',55)" );  
  10.         st.close();  
  11.           
  12.       } catch  (Exception ex) {  
  13.         System.out.println("更新失败" );  
  14.         ts.setRollbackOnly();  
  15.       }  
  16.       return   null ;  
  17.     }  
  18.   });  
  19. }  

三、方法二:通过JdbcTemplate来操作
1.创建JdbcTemplate:

[Java] view plain copy
  1. DataSourceTransactionManager manager = (DataSourceTransactionManager)transactionTemplate.getTransactionManager();  
  2. DataSource ds = manager.getDataSource();  
  3. JdbcTemplate jdbcTemplate = new  JdbcTemplate(ds);  

2.创建之后,执行:

[Java] view plain copy
  1. public   void  addEmployee(Employee employee)  throws  SQLException {  
  2.   transactionTemplate.execute(new  TransactionCallback() {  
  3.     public  Object doInTransaction(TransactionStatus ts) {  
  4.       try  {  
  5.         jdbcTemplate.update("INSERT INTO Employee (username,age) VALUES(?, ?)" ,   
  6.           new  Object[]{ "lizi" , new  Integer( 22 )});  
  7.         jdbcTemplate.update("INSERT INTO Employee (username,age) VALUES(?, ?)" ,   
  8.           new  Object[]{ "lijun" , new  Integer( 55 )});  
  9.         System.out.println("更新成功" );  
  10.   
  11.       } catch  (Exception ex) {  
  12.         System.out.println("更新失败" );  
  13.         ts.setRollbackOnly();  
  14.       }  
  15.       return   null ;  
  16.     }  
  17.   });  
  18. }  

3.问题

  • jdbcTemplate的Connection肯定是从DataSource获取的,但这个Connection是否和TransactionTemplate的事务框架中的已建立的连接是同一个?
  • jdbcTemplate自已的框架也是try{..}catch{..}finally{..},每一个jdbcTemplate.update方法都在这个框架中,会不会执行完后将所用的连接关闭呢?如果关闭,后续方法如何采用同一个连接?

4.jdbcTemplate的连接来源:

[Java] view plain copy
  1. Connection con = DataSourceUtils.getConnection(getDataSource());  

是通过DataSourceUtils的getConnection方法来获取连接的,也就是TransactionSynchronizationManager的线程变量,与事务框架中的连接是同一个.

5.jdbcTemplate的finally会把连接关闭吗?

finally中的代码是:

[Java] view plain copy
  1. DataSourceUtils.closeConnectionIfNecessary(con, getDataSource());  

看看DataSourceUtils

[Java] view plain copy
  1. public   static   void  closeConnectionIfNecessary(Connection con, DataSource dataSource) {  
  2.   try  {  
  3.     doCloseConnectionIfNecessary(con, dataSource);  
  4.   }  
  5.   catch  (SQLException ex) {  
  6.     logger.error("Could not close JDBC connection" , ex);  
  7.   }  
  8. }  
  9.   
  10. protected   static   void  doCloseConnectionIfNecessary(Connection con, DataSource ds)  throws  SQLException {  
  11.   ...  
  12.   ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(ds);  
  13.   if  (conHolder !=  null  && con == conHolder.getConnection()) {  
  14.     //如果是事务中的连接,不需要关闭   
  15.     return ;  
  16.   }  
  17.     
  18.   //非事务连接则关闭   
  19.   if  (!(ds  instanceof  SmartDataSource) || ((SmartDataSource) ds).shouldClose(con)) {  
  20.     logger.debug("Closing JDBC connection" );  
  21.     con.close();  
  22.   }  
  23. }  

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics