标签:
先看一下配置文件(简单配置)
<pre name="code" class="html"><!-- 配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass"> <value>${jdbc.driverClassName}</value> </property> <property name="jdbcUrl"> <value>${jdbc.url}</value> </property> <property name="user"> <value>${jdbc.username}</value> </property> <property name="password"> <value>${jdbc.password}</value> </property> <span style="white-space:pre"> </span></bean>
spring事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean>
这里没用spring注入transactionManager,当然你可以使用spring帮你注入,获取到transactionManager就可以开启事务,这里使用编程式事务的,是因为我要用Connection
/** * 随机获取的连接,用完就释放 */ private Connection queryConnection; /** * 事务连接,有事务期间保留,事务提交后释放 */ private Connection transactionConn ; private DataSourceTransactionManager transactionManager = (DataSourceTransactionManager) ContextLoaderListener.getCurrentWebApplicationContext().getBean("transactionManager"); /** * 事务状态 */ private TransactionStatus transactionStatus;
开启事务和提交事务
public void closeQueryConn() { try { if (this.queryConnection!=null && !this.queryConnection.isClosed() && !this.queryConnection.equals(this.transactionConn)) { this.queryConnection.close(); } } catch (SQLException e) { e.printStackTrace(); } finally { this.queryConnection = null; } } /** * 释放当前线程的session */ public void releaseSession() { if(SessionFactory.getThreadSession() == this) { SessionFactory.releaseSession(); } else { this.closeConn(); } } /** * 开启事务 * @throws SQLException */ public void beginTransaction() throws SQLException{ if(this.transactionStatus == null|| this.transactionStatus.isCompleted()){ //如果有事务连接就把普通查询连接关闭,并把事务连接作为查询连接 this.closeQueryConn(); DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition(); //spring事务的传播行为 PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。 transactionDefinition.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED); //事务的隔离级别 ISOLATION_READ_COMMITTED:表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。 transactionDefinition.setIsolationLevel(DefaultTransactionDefinition.ISOLATION_READ_COMMITTED); //开启事务 this.transactionStatus = this.transactionManager.getTransaction(transactionDefinition); DataSource dataSourcel = this.transactionManager.getDataSource(); this.transactionConn = DataSourceUtils.getConnection(dataSourcel); this.queryConnection = this.transactionConn; } } /** * 提交事务 * @throws SQLException */ public void commitTransaction(){ closeQueryConn(); try { if (this.transactionConn != null && !this.transactionConn.isClosed()) { if (!this.transactionConn.getAutoCommit()) { try { //conn.commit(); this.transactionManager.commit(transactionStatus); } catch (TransactionException e) { //conn.rollback(); this.transactionManager.rollback(transactionStatus); } } this.transactionConn.close(); } } catch (SQLException e) { e.printStackTrace(); } finally{ this.transactionConn=null; } }
针对以上的代码,这里做一些说明:
this.transactionStatus = this.transactionManager.getTransaction(transactionDefinition);开启事务之后this.transactionConn = DataSourceUtils.getConnection(dataSourcel);
获取的连接已经打开事务,this.transactionConn.getAutoCommit()是false
(如果你打开了一个事务没有提交,又打开一个事务即:
transactionStatus1 = this.transactionManager.getTransaction(transactionDefinition);
transactionStatus2 = this.transactionManager.getTransaction(transactionDefinition);
这两个transactionStatus对象不是同一个对象,但是
transactionConn1 = DataSourceUtils.getConnection(dataSourcel);
transactionConn2 = DataSourceUtils.getConnection(dataSourcel);
transactionConn是同一个连接,
transactionManager.commit(transactionStatus2);不会导致transactionStatus1提交,但是transactionManager.commit(transactionStatus1)会提交transactionStatus2的内容,不过transactionStatus2依然显示没有提交,即transactionStatus2.isCompleted()为false)
提交事务之后,this.transactionManager.commit(transactionStatus);this.transactionConn.getAutoCommit()是true
隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量:
所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:
这里需要指出的是,前面的六种事务传播行为是 Spring 从 EJB 中引入的,他们共享相同的概念。而 PROPAGATION_NESTED是 Spring 所特有的。以 PROPAGATION_NESTED 启动的事务内嵌于外部事务中(如果存在外部事务的话),此时,内嵌事务并不是一个独立的事务,它依赖于外部事务的存在,只有通过外部的事务提交,才能引起内部事务的提交,嵌套的子事务不能单独提交。如果熟悉 JDBC 中的保存点(SavePoint)的概念,那嵌套事务就很容易理解了,其实嵌套的子事务就是保存点的一个应用,一个事务中可以包括多个保存点,每一个嵌套子事务。另外,外部事务的回滚也会导致嵌套子事务的回滚。
标签:
原文地址:http://blog.csdn.net/w171203757/article/details/46572719