Spring事务不回滚的解决方法——修改Mysql数据表引擎

在学习Spring事务管理的过程中遇到了一个很是头疼的问题,不管是声明式事务还是注解式事务遇到异常都无法回滚。起初我以为是代码或者软件的问题,但是找了很久都没解决,最后终于发现是MySQL数据表引擎的问题,所以记录下来以防将来再次遇到。


首先简单的项目搭建,这里使用的是注解式事务管理。

(1)创建数据表并插入两条数据

CREATE TABLE t_account(

id INT PRIMARY KEY auto_increment,

username VARCHAR(50),

balance DOUBLE

);

INSERT INTO t_account(username,balance) VALUES('jack',1000);

INSERT INTO t_account(username,balance) VALUES('rose',1000);

(2)创建Spring的配置文件applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
					http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
					http://www.springframework.org/schema/context
					http://www.springframework.org/schema/context/spring-context-4.3.xsd
					http://www.springframework.org/schema/aop
					http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
					http://www.springframework.org/schema/tx
					http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
				
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
	    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
	    <property name="url" value="jdbc:mysql://localhost:3306/spring"/>
	    <property name="username" value="root"/>
	    <property name="password" value="123456"/>
	</bean>
	
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
	    <property name="dataSource" ref="dataSource"/>
	</bean>
	<bean id="accountDao" class="com.itheima.jdbc.AccountDaoImpl">
	    	<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>
	<bean id="transactionManager" 
	    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	    <property name="dataSource" ref="dataSource"/>
	</bean>
	<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

(3)创建AccountDao接口并创建一个转账方法transfer(),然后创建实现类AccountDaoImpl,并添加事务注解

public class AccountDaoImpl implements AccountDao {

	private JdbcTemplate jdbcTemplate;
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false)
	public void transfer(String outUser, String inUser, Double money) {
		this.jdbcTemplate.update("update t_account set balance = balance +? " 
				+ "where username = ?",money,inUser);
		//模拟出现异常
		//int i = 1/0;
		this.jdbcTemplate.update("update t_account set balance = balance -? " 
				+ "where username = ?",money,outUser);
	}
}

(4)创建测试类TransactionTest,测试jack给rose转100块钱

public class TransactionTest {
	@Test
	public void Test() {
		ApplicationContext applicationContext = 
				new ClassPathXmlApplicationContext("applicationContext.xml");
		AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
		accountDao.transfer("jack", "rose", 100.0);
		System.out.println("转账成功");
	}
}

首先把int i=1/0注释掉运行看t_account表的数据

把注释去掉重新运行

rose多了100块钱而jack的金额却没有少,说明事务并没有回滚,原因如下:

这是因为Mysql中的默认引擎是MyISAM,而MyISAM并不支持事务管理,所以将数据表的引擎更改为InnoDB就行了。

MyISAM和InnoDB的基本差别为:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。MyISAM类型的表强调的是性能,其执行速度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持以及外部键等高级数据库功能

更改Mysql数据表的引擎方法:执行sql语句

ALTER TABLE t_account ENGINE=InnoDB;

 

重新运行测试类,结果没有发生改变说明事务回滚了,至此问题解决。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值