经常用到事务管理,可还是不小心会写错,导致事务没有生效,这里总结下。

正确的代码例子如下所示,框架是使用spring+mybatis的,有些配置的就不贴出来了。

TestController2:

package com.test.controller;

import com.alibaba.fastjson.JSON;
import com.cy.service.UserService;
import com.test.dto.Child;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; @Controller
public class TestController2 { @Autowired
private UserService userService; /**
* 测试transcation
*/
@RequestMapping("/testTranscation.do")
public void testTranscation(){
String username = "小王";
String password = "123455";
userService.callAddUserMethod(username, password);
}
}

UserService接口:

package com.cy.service;

import com.cy.entity.User;

/**
* 用户Service接口
* @author Administrator
*
*/
public interface UserService { User login(User user); void addUserMethod(User user); void callAddUserMethod(String username, String password);
}

UserServiceImpl:    

package com.cy.service.impl;

import com.cy.dao.UserDao;
import com.cy.entity.User;
import com.cy.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; /**
* 用户Service实现类
* @author Administrator
*
*/
@Service("userService")
public class UserServiceImpl implements UserService { @Resource(name = "userService")
private UserService userService; @Autowired
private UserDao userDao; @Override
public User login(User user) {
return userDao.login(user);
} @Override
public void callAddUserMethod(String username, String password){
User user = new User();
user.setUsername(username);
user.setPassword(password);
try{
userService.addUserMethod(user);
}catch (Exception e){
System.err.println("addUserMethod异常:" + e.getMessage());
e.printStackTrace();
}
} @Transactional(rollbackFor = Exception.class)
@Override
public void addUserMethod(User user){
int a = userDao.addUser(user);
badMethod();
} private void badMethod(){
int i = 1/0;
} }

UserDao接口:

package com.cy.dao;

import com.cy.entity.User;

public interface UserDao {

    //登录
User login(User user); Integer addUser(User user);
}

UserMapper.xml(这里属于不重要的配置)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cy.dao.UserDao"> <select id="login" parameterType="User" resultType="User">
select * from t_user where username=#{username} and password=#{password}
</select> <insert id="addUser" parameterType="User">
INSERT INTO
t_user(
username,
password
)
VALUES(
#{username},
#{password}
)
</insert>
</mapper>

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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 自动扫描 -->
<context:component-scan base-package="com.cy.service,com.test.service" /> <!-- 配置数据源 -->
<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/demodb"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean> <!-- 配置mybatis的sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描mappers.xml文件 -->
<property name="mapperLocations" value="classpath:com/cy/mappers/*.xml"></property>
<!-- mybatis配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
</bean> <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.cy.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean> <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> </beans>

mybatis-config.xml:(这个是完全不重要的配置)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 别名 -->
<typeAliases>
<package name="com.cy.entity"/>
</typeAliases> </configuration>

测试:

在浏览器中输入:http://localhost:8088/testTranscation.do,发现"小王"并没有被插入数据库,因为报异常回滚掉了。

console中可以看到事务的回滚rollback:

  2019-03-29 14:41:52,411 [http-nio-8088-exec-3] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Acquired Connection [com.mysql.jdbc.JDBC4Connection@3f44f876] for JDBC transaction
2019-03-29 14:41:52,435 [http-nio-8088-exec-3] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Switching JDBC Connection [com.mysql.jdbc.JDBC4Connection@3f44f876] to manual commit
14:41:53.328 [http-nio-8088-exec-3] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
14:41:53.353 [http-nio-8088-exec-3] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5453248e]
14:41:53.384 [http-nio-8088-exec-3] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.mysql.jdbc.JDBC4Connection@3f44f876] will be managed by Spring
14:41:53.437 [http-nio-8088-exec-3] DEBUG com.cy.dao.UserDao.addUser - ==> Preparing: INSERT INTO t_user( username, password ) VALUES( ?, ? )
14:41:53.668 [http-nio-8088-exec-3] DEBUG com.cy.dao.UserDao.addUser - ==> Parameters: 小王(String), 123455(String)
14:41:53.669 [http-nio-8088-exec-3] DEBUG com.cy.dao.UserDao.addUser - <== Updates: 1
14:41:53.669 [http-nio-8088-exec-3] DEBUG org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5453248e]
14:41:59.161 [http-nio-8088-exec-3] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5453248e]
14:41:59.161 [http-nio-8088-exec-3] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5453248e]
2019-03-29 14:41:59,161 [http-nio-8088-exec-3] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Initiating transaction rollback
2019-03-29 14:41:59,161 [http-nio-8088-exec-3] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Rolling back JDBC transaction on Connection [com.mysql.jdbc.JDBC4Connection@3f44f876]
2019-03-29 14:41:59,259 [http-nio-8088-exec-3] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Releasing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3f44f876] after transaction
2019-03-29 14:41:59,259 [http-nio-8088-exec-3] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
addUserMethod异常:/ by zero
java.lang.ArithmeticException: / by zero
at com.cy.service.impl.UserServiceImpl.badMethod(UserServiceImpl.java:51)
at com.cy.service.impl.UserServiceImpl.addUserMethod(UserServiceImpl.java:47)

总结:        

1.@Transactional方法为接口方法,有异常往外抛。 (addUserMethod必须为接口方法)

2.@Transactional方法中可以有私有方法,有异常往外抛。(badMethod)

3.调用@Transactional的方法,可以对它try catch,且必须是接口.方法来调用。(callAddUserMethod中调用addUserMethod,必须是userService.addUserMethod,userServiceImpl把自己注进来)

4.配置文件中必须要有事务管理的配置,缺一不可:

<!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

5.@Transactional方法里面不要try catch异常,但是可以声明throws Exception;

@Transactional方法里面的方法也同样往外抛异常

UserService:

public interface UserService {

    User login(User user);

    void addUserMethod(User user) throws ArithmeticException;

    void callAddUserMethod(String username, String password);
}

UserServiceImpl:

package com.cy.service.impl;

import com.cy.dao.UserDao;
import com.cy.entity.User;
import com.cy.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; /**
* 用户Service实现类
* @author Administrator
*
*/
@Service("userService")
public class UserServiceImpl implements UserService { @Resource(name = "userService")
private UserService userService; @Autowired
private UserDao userDao; @Override
public User login(User user) {
return userDao.login(user);
} @Override
public void callAddUserMethod(String username, String password){
User user = new User();
user.setUsername(username);
user.setPassword(password);
try{
userService.addUserMethod(user);
}catch (Exception e){
System.err.println("addUserMethod异常:" + e.getMessage());
e.printStackTrace();
}
} @Transactional(rollbackFor = Exception.class)
@Override
public void addUserMethod(User user) throws ArithmeticException{
int a = userDao.addUser(user);
badMethod();
} private void badMethod() throws ArithmeticException{
try{
int i = 1/0;
}catch (ArithmeticException e){
throw e;
}
} }

transcation事务也是生效的。

@Transactional的正确打开方式的更多相关文章

  1. iOS开发小技巧--相机相册的正确打开方式

    iOS相机相册的正确打开方式- UIImagePickerController 通过指定sourceType来实现打开相册还是相机 UIImagePickerControllerSourceTypeP ...

  2. Xcode 的正确打开方式——Debugging(转载)

    Xcode 的正确打开方式——Debugging   程序员日常开发中有大量时间都会花费在 debug 上,从事 iOS 开发不可避免地需要使用 Xcode.这篇博客就主要介绍了 Xcode 中几种能 ...

  3. C#语法——泛型的多种应用 C#语法——await与async的正确打开方式 C#线程安全使用(五) C#语法——元组类型 好好耕耘 redis和memcached的区别

    C#语法——泛型的多种应用   本篇文章主要介绍泛型的应用. 泛型是.NET Framework 2.0 版类库就已经提供的语法,主要用于提高代码的可重用性.类型安全性和效率. 泛型的定义 下面定义了 ...

  4. InnoDB缓冲池预加载在MySQL 5.7中的正确打开方式

    InnoDB缓冲池预加载在MySQL 5.7中的正确打开方式 https://mp.weixin.qq.com/s/HGa_90XvC22anabiBF8AbQ 在这篇文章里,我将讨论在MySQL 5 ...

  5. Console控制台的正确打开方式

    Console控制台的正确打开方式 console对象提供了访问浏览器调试模式的信息到控制台 -- Console对象 |-- assert() 如果第一个参数断言为false,则在控制台输出错误信息 ...

  6. 任务队列和异步接口的正确打开方式(.NET Core版本)

    任务队列和异步接口的正确打开方式 什么是异步接口? Asynchronous Operations Certain types of operations might require processi ...

  7. (一)Redis for Windows正确打开方式

    目录 (一)Redis for Windows正确打开方式 (二)Redis for 阿里云公网连接 (三)Redis for StackExchange.Redis 下载地址 官网.中文网1 及 中 ...

  8. List的remove()方法的三种正确打开方式

    转: java编程:List的remove()方法的三种正确打开方式! 2018年08月12日 16:26:13 Aries9986 阅读数 2728更多 分类专栏: leetcode刷题   版权声 ...

  9. C++11随机数的正确打开方式

    C++11随机数的正确打开方式 在C++11之前,现有的随机数函数都存在一个问题:在利用循环多次获取随机数时,如果程序运行过快或者使用了多线程等方法,srand((unsigned)time(null ...

随机推荐

  1. Python使用requests库,requests.post格式会引发参数不存在问题

    Content-Type: application/json #############↓↓↓成功↓↓↓############# import requests url = 'http://loca ...

  2. SQA

    SQA 一.SQA过程 首先组成一个团队,遵循敏捷开发的原则,进行分工合作,为软件开发编造一个用例故事,画出相应的图,小组讨论合作后写代码,软件质量保证(SQA-Software Quality As ...

  3. WPF: 在ListView中添加Checkbox列表

    描述:ListView是WPF中动态绑定工具的数据容器,本文实现了一个在ListView中显示的供用户选择的列表项目,并且控制列表中选择的项目数量,即实现单选. XAML中创建ListView,代码如 ...

  4. HTML5 Canvas爱心时钟代码

    这是一款数字时钟动画,数字又多个小爱心组成,又何问起整理,随着时间推进,每一秒钟新数字替换旧数字,旧数字离去使用天女散花动画,花是五颜六色的. 查看效果:http://hovertree.com/te ...

  5. 埃式筛法——求n以内素数

    素数筛法的关键就在一个“筛”字.算法从小到大枚举所有数,对每一个素数,筛去它的所有倍数,剩下的就都是素数了. 例如:求1-15中的所有素数. 1.  2是素数(唯一需要事先确定的),因此筛去2的所有倍 ...

  6. js复习--基础

    最近工作遇到了一些小困难,基础真的很重要,漫天高楼起于地. 一,script元素 包括type=“text/Javascript”,defer延迟到html加载完解析,src=“../../test. ...

  7. npm,bower安装失败

    安装一些软件时,总是会出现一些莫名其妙的问题.我在安装node.js时,默认安装到C:\Program Files\nodejs之后,安装bower时,bower_components默认装到C:\W ...

  8. java根据ip地址获取详细地域信息的方法

    通过淘宝IP地址库获取IP位置(也可以使用新浪的) 请求接口(GET):http://ip.taobao.com/service/getIpInfo.php?ip=[ip地址字串] 响应信息:(jso ...

  9. Node.Js http服务(websocket)

    安装node,下载地址 https://nodejs.org/en/ cmd 中 输入 node -v 安装成功可以查看版本 cmd 中 ctrl - c 可以 结束 和 启动 编辑 js 文本 va ...

  10. 软件可维护性的影响因素&如何提升

    影响因素: 1.可理解性 2.可测试性 3.可修改性 4.可移植性 5.可重用性 如何提升: 1.建立明确的软件质量目标2.使用先进的软件开发技术和工具3.建立明确的质量保证4.选择可维护的语言5.改 ...