日期:2014-05-16  浏览次数:20753 次

使用Hibernate、Spring和MySQL时,谨慎选择MySQL的表类型

Hibernate采用的是write-behind的策略。MySQL的MyISAM类型,是不支持事务的,InnoDB类型支持事务。

现在有如下方法,假设表类型为MyIASM。
@Transaction
public void someMethod(User user) {
??? user.setAge(28);
??? update(user);
??? flush();
??? xxxDao.updateCategory(user.getCategory());

??? throw new RuntimeException();
}

?

现在,执行这个方法,会发生什么事情呢?可以发现,用户被更新了,但是,xxxDao执行的更新被回滚了。

天哪,太可怕了!是这样的,flush()会导致Hibernate将session中的内容同步到数据库,但是此时还是可以回滚的,前提是数据库支持事务。否则就一定会被同步到数据库,但是下面那条语句,因为抛出了异常,实际上session内缓存的内容是没有同步到数据库的。

?

将表类型修改为InnoDB后,问题解决,可以正确回滚。所以,平常写程序的过程中,尤为注意,要慎用flush(),且一定要谨慎选择MySQL的表类型,重要数据的表,一定要采用InnoDB类型,确保事务可以正确执行。

?

另外,不仅是flush()会立即将session的内容同步到数据库,自增主键的表,当执行insert的时候,也一样会立即写入数据,因为持久化对象必须拥有一个主键,加入您采用了MyIASM,且这个方法有事务,后面还抛出了异常的话。那个之前的保存是不会再回滚了,已经写入到数据库了。

?

?