spring + hibernate + mysql 事务不回滚

首先声明,这个问题涉及到的数据库是MySQL。
这是个很奇怪的问题,事务怎么会不回滚呢?实际上这是个愚蠢的问题,是经验不足导致的,越是奇怪的问题解决起来就越容易。
不回滚的根本原因不在Hibernate,更不是SSH框架,而在MySQL本身。


查看MySQL数据库使用的存储引擎:
mysql>show variables like '%storage_engine%';
结果:
+----------------+--------+ 
|Variable_name |Value| 
+----------------+--------+ 
|storage_engine|InnoDB
+----------------+--------+ 
1 row in set


查看MySQL 提供什么存储引擎:
mysql>show engines;
结果:
+------------+---------+----------------------------------------------------------------+--------------+------+------------+ | Engine | Support | Comment | Transactions | XA | Savepoints | +------------+---------+----------------------------------------------------------------+--------------+------+------------+ | MyISAM | YES | Default engine as of MySQL 3.23 with great performance | NO | NO | NO | | CSV | YES | CSV storage engine | NO | NO | NO | | MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO | | BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | | FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL | | InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES | | ARCHIVE | YES | Archive storage engine | NO | NO | NO | | MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO | +------------+---------+----------------------------------------------------------------+--------------+------+------------+ 8 rows in set

从结果上看,当前数据库的默认存储引擎是InnoDB(注意观察Support这一列的值),不过有的数据库却不是,它们默认的是 MyISAM。非但如此,在Support一栏中还显示NO,就是说连InnoDB都不支持。
这就是为什么不回滚的原因:InnoDB支持事务,而MyISAM不支持!
其实MyISAM是MySQL默认的存储引擎,在安装MySQL时如果没有指定存储引擎,那么MySQL会默认使用MyISAM,因为它不支持事务,也许效率会比InnoDB高一些。

如果使用的是MyISAM,那么需要将其改为InnoDB,具体方法如下:
1、打开“MySQL_HOME/my.ini”,找到[mysqld],在它的下面有一句话是“skip-innodb”,将其注释掉,即改为:#skip-innodb。
2、 [mysqld]下加上一句“ default_table_type=INNODB ”(如果写成 default-storage-engine=INNODB也可以,两者之间的区别我还没有研究过
3、重启MySQL服务(注意:是重启服务,不是光退出数据库就完事了!)
4、 再次执行 mysql> show engines;可以看见默认存储引擎已经变成InnoDB了。
5、原来已经存在的表,如果想使用事务,要修改它的存储引擎,在默认是InnoDB的情况下删除重建。
当不想删除的时候,执行
alter table 表名 ENGINE = InnoDB;
之后执行
show table status from 数据库名 where name='表名';
可以查看表状态,看存储引擎是否被修改了。

在使用了InnoDB引擎之后,再次运行代码,回滚成功!

猜你喜欢

转载自scjava.iteye.com/blog/1632349
今日推荐