团队技术核心成员写的,这个问题,导致其开发的销售模块事务无法回滚,数据库外键均变成索引
原博客:http://blog.csdn.net/lzx_longyou/article/details/50446206
最近在做一个项目,用的是hibernate框架,数据库是mysql。我是在javaweb的过滤器上通过session与线程绑定,得到当前线程绑定的session然后开启事务,然后进行放心,对异常进行捕获并回滚。这是在没有使用spring框架的事务处理,而又为了延长hibernate中session的声明周期所采用的方法,即OpenSessinInView。在过滤器开启事务后,放行执行的代码都会在事务之内,出现异常进行捕获可以回滚。代码如下:
- public class OpenSessionInView implements Filter {
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- Session session = null;
- Transaction tx = null;
- try {
- session = ClientSessionFactory.getCurrentSession();
- tx = session.beginTransaction();
- //=======业务开始=======
- chain.doFilter(request, response);
- //=======业务结束=======
- tx.commit();
- } catch (AjaxException e) {
- response.setCharacterEncoding("utf-8");
- if (tx != null) {
- tx.rollback();
- }
- String error = e.getMessage();
- response.getWriter().print(error);
- } catch (Exception e) {
- if (tx != null) {
- tx.rollback();
- }
- e.printStackTrace();
- request.setAttribute("error", e.getMessage());
- request.getRequestDispatcher("/jsps/error.jsp")
- .forward(request, response);
- } finally{
- ClientSessionFactory.closeCurrentSession();
- }
- }
- public void init(FilterConfig fConfig) throws ServletException {
- }
- public void destroy() {
- }
- }
在实际情况中,我在servlet中执行了一个添加函数,往数据库中添加一条记录,然后继续执行下面的代码,结果发生了异常。这时发现,数据库中的数据并没有回滚。在设置断点调试后,发现,过滤器中的事务有开启,异常也有被捕获,事务回滚的代码也有被执行,但是数据库中的数据就是不回滚,造成了垃圾数据的产生。
同时,也发现了数据库中存在的一个问题,所有建的外键,都无效,自动变成了索引,真的是奇怪。
后来在网上找了很久,才发现这不是代码的问题,而是数据库的问题。MySQL数据库的存储引擎有好几种,有的不支持事务和外键,有的支持。在mysql中输入sql语句 SHOW ENGINES可以查看当前数据库支持的引擎:
第二列Support中DEFAULT表示目前数据库的默认引擎。这个引擎是管理非事务表,不支持事务,不支持外键,但是访问速度快,对事务完整性没有要求或者以SELECT、INSERT为主的应用基本都可以使用这个引擎来创建表。这也就解释了我遇到的数据库不能回滚,表不能建外键的原因。
从图中可以看到,只有InnoDB这个引擎支持了事务,所以想在程序中使用事务,并在出现异常时回滚,就要使用这个引擎,即修改一下表的引擎即可。
至此之前的问题都解决了。有时候思考一个问题,不能太单方面,从多角度思考或许就能找到问题的根源。
关于MySQL数据库引擎的介绍,可参考下面一篇博客:
http://www.cnblogs.com/gbyukg/archive/2011/11/09/2242271.html