首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

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

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

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 plaincopy
  1. private?static?Connection?getConnection(TransactionStatus?ts)?{????JdbcTransactionObjectSupport?transObj?=?(JdbcTransactionObjectSupport)((DefaultTransactionStatus)ts).getTransaction();??
  2. ??ConnectionHolder?holder?=?transObj.getConnectionHolder();????Connection?con?=?holder.getConnection();??
  3. ??return?con;??}??

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

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

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

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

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

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

2.创建之后,执行:

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

3.问题

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

4.jdbcTemplate的连接来源:

[Java] view plaincopy
  1. Connection?con?=?DataSourceUtils.getConnection(getDataSource());??

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

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

finally中的代码是:

[Java] view plaincopy
  1. DataSourceUtils.closeConnectionIfNecessary(con,?getDataSource());??

看看DataSourceUtils

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

?

热点排行