spring 1.1.3 JDBC编程式事务管理探析(二):怎么实现TransactionTemplate.execute的回调接口TransactionCal
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
- private?static?Connection?getConnection(TransactionStatus?ts)?{????JdbcTransactionObjectSupport?transObj?=?(JdbcTransactionObjectSupport)((DefaultTransactionStatus)ts).getTransaction();??
- ??ConnectionHolder?holder?=?transObj.getConnectionHolder();????Connection?con?=?holder.getConnection();??
- ??return?con;??}??
2.从TransactionSynchronizationManager的线程变量中获取
[Java] view plaincopy
- private?Connection?getConnection()?{????DataSourceTransactionManager?manager?=?(DataSourceTransactionManager)transactionTemplate.getTransactionManager();??
- ??DataSource?ds?=?manager.getDataSource();????return?DataSourceUtils.getConnection(ds);//??
- }??
这里贴出DataSourceUtils.getConnection(ds)的部分代码:
[Java] view plaincopy
- public?static?Connection?getConnection(DataSource?dataSource,?boolean?allowSynchronization)????throws?CannotGetJdbcConnectionException?{??
- ??try?{??????return?doGetConnection(dataSource,?allowSynchronization);??
- ??}????catch?(SQLException?ex)?{??
- ????throw?new?CannotGetJdbcConnectionException("Could?not?get?JDBC?connection",?ex);????}??
- }????
- protected?static?Connection?doGetConnection(DataSource?dataSource,?boolean?allowSynchronization)????throws?SQLException?{??
- ??...????ConnectionHolder?conHolder?=?(ConnectionHolder)?TransactionSynchronizationManager.getResource(dataSource);??
- ??if?(conHolder?!=?null)?{??????return?conHolder.getConnection();??
- ??}????...??
- }??
获取了Connection之后,就可以按照常规的方法来操作SQL语句了
[Java] view plaincopy
- public?void?addEmployee1(Employee?employee)?throws?SQLException?{????transactionTemplate.execute(new?TransactionCallback()?{??
- ????public?Object?doInTransaction(TransactionStatus?ts)?{????????try?{??
- ????????//Connection?con?=?getConnection(ts);??????????Connection?con?=?getConnection();??
- ????????Statement?st?=?con.createStatement();??????????st.executeUpdate("INSERT?INTO?Employee?(username,age)?VALUES('lizi',?22)");??
- ????????st.executeUpdate("INSERT?INTO?Employee?(username,age)?VALUES('lijun',55)");??????????st.close();??
- ????????????????}?catch?(Exception?ex)?{??
- ????????System.out.println("更新失败");??????????ts.setRollbackOnly();??
- ??????}????????return?null;??
- ????}????});??
- }??
三、方法二:通过JdbcTemplate来操作
1.创建JdbcTemplate:
[Java] view plaincopy
- DataSourceTransactionManager?manager?=?(DataSourceTransactionManager)transactionTemplate.getTransactionManager();??DataSource?ds?=?manager.getDataSource();??
- JdbcTemplate?jdbcTemplate?=?new?JdbcTemplate(ds);??
2.创建之后,执行:
[Java] view plaincopy
- public?void?addEmployee(Employee?employee)?throws?SQLException?{????transactionTemplate.execute(new?TransactionCallback()?{??
- ????public?Object?doInTransaction(TransactionStatus?ts)?{????????try?{??
- ????????jdbcTemplate.update("INSERT?INTO?Employee?(username,age)?VALUES(?,??)",?????????????new?Object[]{"lizi",new?Integer(22)});??
- ????????jdbcTemplate.update("INSERT?INTO?Employee?(username,age)?VALUES(?,??)",?????????????new?Object[]{"lijun",new?Integer(55)});??
- ????????System.out.println("更新成功");????
- ??????}?catch?(Exception?ex)?{??????????System.out.println("更新失败");??
- ????????ts.setRollbackOnly();????????}??
- ??????return?null;??????}??
- ??});??}??
3.问题
jdbcTemplate的Connection肯定是从DataSource获取的,但这个Connection是否和TransactionTemplate的事务框架中的已建立的连接是同一个?jdbcTemplate自已的框架也是try{..}catch{..}finally{..},每一个jdbcTemplate.update方法都在这个框架中,会不会执行完后将所用的连接关闭呢?如果关闭,后续方法如何采用同一个连接?
4.jdbcTemplate的连接来源:
[Java] view plaincopy
- Connection?con?=?DataSourceUtils.getConnection(getDataSource());??
是通过DataSourceUtils的getConnection方法来获取连接的,也就是TransactionSynchronizationManager的线程变量,与事务框架中的连接是同一个.
5.jdbcTemplate的finally会把连接关闭吗?
finally中的代码是:
[Java] view plaincopy
- DataSourceUtils.closeConnectionIfNecessary(con,?getDataSource());??
看看DataSourceUtils
[Java] view plaincopy
- public?static?void?closeConnectionIfNecessary(Connection?con,?DataSource?dataSource)?{????try?{??
- ????doCloseConnectionIfNecessary(con,?dataSource);????}??
- ??catch?(SQLException?ex)?{??????logger.error("Could?not?close?JDBC?connection",?ex);??
- ??}??}??
- ??protected?static?void?doCloseConnectionIfNecessary(Connection?con,?DataSource?ds)?throws?SQLException?{??
- ??...????ConnectionHolder?conHolder?=?(ConnectionHolder)?TransactionSynchronizationManager.getResource(ds);??
- ??if?(conHolder?!=?null?&&?con?==?conHolder.getConnection())?{??????//如果是事务中的连接,不需要关闭??
- ????return;????}??
- ??????//非事务连接则关闭??
- ??if?(!(ds?instanceof?SmartDataSource)?||?((SmartDataSource)?ds).shouldClose(con))?{??????logger.debug("Closing?JDBC?connection");??
- ????con.close();????}??
- }??
?