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

正确的代码例子如下所示,框架是使用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. OGNL表达式的一个坑!

    我在写Spring整合JDBC框架的时候用了properties文件去设置JDBC的参数.但是发现了一个问题先付上代码 properties文件的代码 db.driverClass=com.mysql ...

  2. Mac下截屏方法

    Refer to:https://zh.wikihow.com/在Mac-OS-X上截取屏幕截图 先来说几个需要用到的Mac键盘和普通键盘不一样的名字: Mac键盘 普通键盘 control Ctrl ...

  3. 华莱士的 第一个python程序之(用户登录)

    Name = "shangzb"password = 43while True: _Name = input("Name:") if _Name == Name ...

  4. 【EMV L2】终端验证结果(Terminal Verification Results,TVR)

    终端验证结果,Terminal Verification Results(TVR),Tag95,5bytes: 记录交易过程中,数据认证.处理限制.持卡人验证.终端风险管理.行为分析以及联机处理的结果 ...

  5. Mac os系统gdb调试器的安装与使用

    Mac os系统gdb调试器的安装与使用 1.简介 Mac os下的Terminal 终端中默认情况下并没有安装gdb调试器,但是可以通过gcc编译器进行代码编译,如果出错了就需要通过gdb调试器进行 ...

  6. eclipse通过maven进行打编译

    对maven项目中pom.xml右键-->Run As-->Maven build... Goals里面添加assembly:assembly 点击run,编译成功后jar包在target ...

  7. Appium环境搭建——安卓真机调试注意点

    1.安卓设备连接失败 通过adb devices命令 查看安卓设备的连接情况,如图,未成功连接 解决方法: (1)关闭360安全卫士和360手机助手(2)查看5037端口是否被占用 netstat - ...

  8. BootStrap的table技术小结:数据填充、分页、列宽可拖动

    本文结构:先说明,后代码.拷贝可直接运行. 一.demo结构: 二.文件引入 这些里面除了下面2个比较难找,其他的都很好找 bootstrap-table-resizable.js colResiza ...

  9. Python基础:八、python基本数据类型

    一.什么是数据类型? 我们人类可以很容易的分清数字与字符的区别,但是计算机并不能,计算机虽然很强大,但从某种角度上来看又很傻,除非你明确告诉它,"1"是数字,"壹&quo ...

  10. 《python for data analysis》第九章,数据聚合与分组运算

    # -*- coding:utf-8 -*-# <python for data analysis>第九章# 数据聚合与分组运算import pandas as pdimport nump ...