解决Transaction is already completed - do not call commit or rollback more than once per transaction问题

问题

        在看《Spring揭秘》事务章节内容,调试代码过程中,出现以下异常:

19/01/29 14:41:31 [main]: DEBUG datasource.DataSourceTransactionManager: Creating new transaction with name [ChansonTransaction]: PROPAGATION_REQUIRES_NEW,ISOLATION_READ_COMMITTED
19/01/29 14:41:31 [main]: DEBUG datasource.DataSourceTransactionManager: Acquired Connection [jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=UTF-8&useSSL=false, UserName=root@localhost, MySQL Connector Java] for JDBC transaction
19/01/29 14:41:31 [main]: DEBUG datasource.DataSourceUtils: Changing isolation level of JDBC Connection [jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=UTF-8&useSSL=false, UserName=root@localhost, MySQL Connector Java] to 2
19/01/29 14:41:31 [main]: DEBUG datasource.DataSourceTransactionManager: Switching JDBC Connection [jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=UTF-8&useSSL=false, UserName=root@localhost, MySQL Connector Java] to manual commit
19/01/29 14:41:31 [main]: DEBUG core.JdbcTemplate: Executing prepared SQL update
19/01/29 14:41:31 [main]: DEBUG core.JdbcTemplate: Executing prepared SQL statement [UPDATE t_user SET password=? WHERE user_name =?]
19/01/29 14:41:31 [main]: DEBUG core.JdbcTemplate: SQL update affected 1 rows
19/01/29 14:41:31 [main]: DEBUG datasource.DataSourceTransactionManager: Initiating transaction rollback
19/01/29 14:41:31 [main]: DEBUG datasource.DataSourceTransactionManager: Rolling back JDBC transaction on Connection [jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=UTF-8&useSSL=false, UserName=root@localhost, MySQL Connector Java]
19/01/29 14:41:31 [main]: DEBUG datasource.DataSourceUtils: Resetting isolation level of JDBC Connection [jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=UTF-8&useSSL=false, UserName=root@localhost, MySQL Connector Java] to 4
19/01/29 14:41:31 [main]: DEBUG datasource.DataSourceTransactionManager: Releasing JDBC Connection [jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=UTF-8&useSSL=false, UserName=root@localhost, MySQL Connector Java] after transaction
19/01/29 14:41:31 [main]: DEBUG datasource.DataSourceUtils: Returning JDBC Connection to DataSource
Exception in thread "main" org.springframework.transaction.IllegalTransactionStateException: Transaction is already completed - do not call commit or rollback more than once per transaction
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:697)
	at springjiemi.platformtransaction.UserService.update(UserService.java:42)
	at springjiemi.platformtransaction.UserService.main(UserService.java:50)

 

分析

日志显示存在事务多次提交的问题。

分析了一下源代码:

public void update(String userName) {
		
		DefaultTransactionDefinition transactionDefinition  = new DefaultTransactionDefinition();
		transactionDefinition.setName("ChansonTransaction");
		//默认:TransactionDefinition.ISOLATION_DEFAULT
		transactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
		//默认:TransactionDefinition.PROPAGATION_REQUIRED
		transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
		TransactionStatus txStatus = platformTransactionManager.getTransaction(transactionDefinition);
		try {
			userDao1.doDataAccess(userName);
			int i = 9/0;
			userDao2.doDataAccess(userName);
		} catch (DataAccessException e) {
			platformTransactionManager.rollback(txStatus);			
		} catch (Exception e) {
			platformTransactionManager.rollback(txStatus);
		}
		platformTransactionManager.commit(txStatus);
	}

        由于异常被catch,而在catch时,进行了事务回滚,正常在此应该退出方法处理(程序直接返回或者抛出异常),但事实上程序直接执行了后续的代码:platformTransactionManager.commit(txStatus);所以报错。
         

解决

        解决方法:在catch过程中,抛出异常,结束方法执行。

public void update(String userName) {
		
		DefaultTransactionDefinition transactionDefinition  = new DefaultTransactionDefinition();
		transactionDefinition.setName("ChansonTransaction");
		//默认:TransactionDefinition.ISOLATION_DEFAULT
		transactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
		//默认:TransactionDefinition.PROPAGATION_REQUIRED
		transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
		TransactionStatus txStatus = platformTransactionManager.getTransaction(transactionDefinition);
		try {
			userDao1.doDataAccess(userName);
			int i = 9/0;
			userDao2.doDataAccess(userName);
		} catch (DataAccessException e) {
			platformTransactionManager.rollback(txStatus);
			throw e;
		} catch (Exception e) {
			platformTransactionManager.rollback(txStatus);
			throw e;
		}
		platformTransactionManager.commit(txStatus);
	}

文章结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值