背景

近期在公司做的一个项目,用的是SpringMVC框架,数据库用的是MySql,刚開始并没有增加事务,后因业务须要必须事务处理。

问题的产生和解决

使用事务,直接问百度,我选择的是注解的方式。

在配置文件里配置事务管理器和驱动:

<tx:annotation-driven transaction-manager="transactionManager"/>

       <bean
id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>

然后直接在service层加注解

package com.my.service.impl;

import java.sql.SQLException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import com.my.constants.ServiceException;
import com.my.dao.TestDao;
import com.my.service.TestService; @Service
public class TestServiceImpl implements TestService{ @Autowired
private TestDao testDao; @Override
@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = { ServiceException.class })
public int insertUser(String userName) throws ServiceException {
int id = 0;
try {
id = testDao.insertUser(userName);
} catch (SQLException e) {
throw new ServiceException();
}
return id;
}
}

自然地,rollback的异常要和service抛出的异常一样才会回滚。

然后自觉得代码肯定没有问题。但是多次debug后到数据库取看都没有回滚,于是就直接在代码中增加错误代码int i = 5/0。并把exception的捕获改动一下

package com.my.service.impl;

import java.sql.SQLException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import com.my.constants.ServiceException;
import com.my.dao.TestDao;
import com.my.service.TestService; @Service
public class TestServiceImpl implements TestService{ @Autowired
private TestDao testDao; @Override
@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = { ServiceException.class })
public int insertUser(String userName) throws ServiceException {
int id = 0;
try {
id = testDao.insertUser(userName);
int i = 5/0;
} catch (Exception e) {
throw new ServiceException();
}
return id;
} }

用上面的代码多次调试。始终没有回滚。

然后自然想到,可能Dao层有问题。然后去看Dao层代码,似乎真的有问题:

package com.my.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository; import com.my.dao.TestDao; @Repository
public class TestDaoImpl implements TestDao { @Autowired
private JdbcTemplate jdbcTemplate; @Override
public int insertUser(final String userName) throws SQLException {
final String sql = "INSERT INTO USER(NAME) VALUES(?);";
KeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement ps = jdbcTem-plate.getDataSource().getConnection().prepareStatement(sql);
ps.setString(1, userName); return ps;
}
}, keyHolder); return keyHolder.getKey().intValue();
}
}

错误可能就在代码黄色块。

于是debug进去,看到Connectioncon中的autoCommit属性是false的,显然是被service层的事务管理到的,而jdbcTemplate.getDataSource().getConnection()是到链接池又一次获取的连接。这个连接显然没有被事务管理。它的autoCommit属性显然是true,所以这使得service层事务没有回滚。改起来非常easy,直接把代码中的黄色块改成PreparedStatement
ps = con.prepareStatement(sql);就能够了。

总结

遇到Springmvc事务不能回滚。解决的步骤:

1.  检查配置文件中面有没有增加事务管理配置和驱动;

2.  检查数据库是否支持事务(比如MySql4.0 支持事务,Engine:InnoDB);

3.  检查代码块是否抛出异常,且事务的rollback的异常是抛出异常或者是抛出异常的父类。

4.  检查事务覆盖的代码块中的全部Connection是否都被这个事务覆盖(debug检查全部connection的autoCommit属性是不是被事务改成了false)。

Spring @Transaction配置演示样例及发生不回滚原因深度剖析的更多相关文章

  1. Nginx 简单的负载均衡配置演示样例

    近期在做开放查询应用的时候,因为数据两天特别多,两千多万条呢,用户訪问需求也比較大,所以就用nginx做了 负载均衡,以下是改动之后的相关内容. http://www.cnblogs.com/xiao ...

  2. AOP经典2种配置演示样例

    第一种: 使用aop指定切面aspect. <bean id="LogAdvice" class="com.thinkmore.framework.monitor. ...

  3. EEPlat vs saleforce 配置 Knowledge Article 演示样例

    ==================================================================================================== ...

  4. JBoss 系列一 O O:Maven jBPM 6 集成演示样例

    概述 jBPM 6 中底层架构基于 Maven,所以我们能够非常easy的进行 Maven jBPM 6 集成演示样例,本文分三个部分: 基本原理介绍 Maven jBPM 6 集成 jBPM 6 中 ...

  5. Cocos2d-x 3.2Lua演示样例UserDefaultTest(用户默认配置)

    Cocos2d-x 3.2演示样例UserDefaultTest(用户默认配置) 本篇博客介绍Cocos2d-x 3.2演示样例中的UserDefaulstTest,我们在开发中可能须要用到一些默认配 ...

  6. Tuxedo安装、配置、以及演示样例程序 (学习网址)

    Tuxedo安装.配置.以及演示样例程序 (学习网址): 1.http://liu9403.iteye.com/blog/1415684 2.http://www.cnblogs.com/fnng/a ...

  7. SNF快速开发平台MVC-各种级联绑定方式,演示样例程序(包含表单和表格控件)

    做了这么多项目,经常会使用到级联.联动的情况. 如:省.市.县.区.一级分类.二级分类.三级分类.仓库.货位. 方式:有表单需要做级联的,还是表格行上需要做级联操作的. 实现:实现方法也有很多种方式. ...

  8. Eureka 的 Application Service client的注冊以及执行演示样例

            Eureka 服务器架起来了(关于架设步骤參考博客<Linux 下 Eureka 服务器的部署>),如今怎样把我们要负载均衡的服务器(也就是从 Application Cl ...

  9. JDBC连接MySQL数据库及演示样例

    JDBC是Sun公司制定的一个能够用Java语言连接数据库的技术. 一.JDBC基础知识         JDBC(Java Data Base Connectivity,java数据库连接)是一种用 ...

随机推荐

  1. MySQL基础 - Navicat及HeidiSQL可视化数据库管理工具

    你还在使用终端界面查看数据库吗?是的,用来用去还是觉得命令行好用.....这里先留个位子,改天再介绍下这俩工具的使用,虽然好像觉得没啥需要介绍的.

  2. Jenkins的授权和访问控制

    默认的Jenkins不包含任何的安全检查,任何人可以修改Jenkins设置,job和启动build等.显然地在大规模的公司需要多个部门一起协调工作的时候,没有任何安全检查会带来很多的问题. 在系统管理 ...

  3. CVE-2010-2553 Microsoft Windows Cinepak 编码解码器解压缩漏洞 分析

      Microsoft Windows是微软发布的非常流行的操作系统.         Microsoft Windows XP SP2和SP3,Windows Vista SP1和SP2,以及Win ...

  4. JavaWeb--中文乱码小结

    JavaWeb--中文乱码小结 出处:http://chriszz.sinaapp.com0.纯粹html乱码: 换个editor吧(有时候notepad都比sublime_text好用),最好是在& ...

  5. 二进制方式部署Kubernetes 1.6.0集群(开启TLS)

    本节内容: Kubernetes简介 环境信息 创建TLS加密通信的证书和密钥 下载和配置 kubectl(kubecontrol) 命令行工具 创建 kubeconfig 文件 创建高可用 etcd ...

  6. CF 576A 猜数

    A给出一个数x,B每次猜一个y,A回答B,x是否可以被y整除,求出要猜的最小次数和需要猜的数. 枚举每个素数p,可以知道如果p^k<=n,则p^k一定需要选 Sample test(s)inpu ...

  7. CCF CSP 201604-3 路径解析

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201604-3 路径解析 问题描述 在操作系统中,数据通常以文件的形式存储在文件系统中.文件系 ...

  8. OS X 配置 Apache

    1.去掉javascript:void(0);Include /private/etc/apache2/extra/httpd-vhosts.con的注释,以启用虚拟主机: 2.在<Direct ...

  9. MFC+WinPcap编写一个嗅探器之七(协议)

    这一节是本系列教程的结尾了,内容也比较简单,主要是对网络协议进行分析,其实学过计算机网络的同学完全可以略过 在整个项目中需要有一个头文件存放各层协议的头部定义,我把它们放在了head.h中,这个头文件 ...

  10. 洛谷 P2042 [NOI2005]维护数列-Splay(插入 删除 修改 翻转 求和 最大的子序列)

    因为要讲座,随便写一下,等讲完有时间好好写一篇splay的博客. 先直接上题目然后贴代码,具体讲解都写代码里了. 参考的博客等的链接都贴代码里了,有空再好好写. P2042 [NOI2005]维护数列 ...