SSM学习记录(五)——通过注解及AOP进行事务管理

2018.5.4

仅为个人理解 不足之处欢迎指正~


什么是事务管理?

事务管理是对于一系列数据库操作进行管理,一个事务包含一个或多个SQL语句,是逻辑管理的工作单元(原子单元)

事务管理的核心在于 回 滚


什么情况下需要事务管理?

对数据库中的数据进行批量操作或多表操作时,为了保证数据的正确性和一致性,需要添加事务管理机制进行管理


举例说明:

银行转账操作细分为两个步骤:(A向B转账100元)

(1)A用户账户余额减少100元

(2)B用户账户余额增加100元

那么假如当执行完(1)步骤而未完成(2)步骤时

情况发生变化 如服务器宕机 或者用户取消转账

那此时A的余额减少而B的余额没有增加 势必会造成错误


不进行事务管理的情况

由于之前的项目是各种登录注册之类的业务 较难模拟真实的需要事务管理的操作

我们假想以下操作:

连续注册两个用户 其中第一个用户合理 第二个用户的用户名超过了数据库中定义的最大长度

将这两个插入过程等价于转账中的减少余额与增加余额

第二个插入失败 则第一个插入的结果应该撤销


在UserService.java中增加一个测试方法:


和他的实现:



编写Controller接受指令:

package controller;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import pojo.User;
import service.UserService;

@Controller
public class TestController 
{
	@Resource
	UserService userService;
	@RequestMapping("/shiwuguanli")  
     public ModelAndView shiwuguanli()
    {  
            ModelAndView mv = new ModelAndView("welcome");
            userService.add2User();
            return mv;
      }
}

运行程序并测试:


服务器报错 此时查看数据库:


发现第一个插入操作完成 第二个未完成


使用注解进行事务管理

第一步:

在spring-mybatis配置文件中加入:


注:jdbcDataSource为自己配置的数据池名称


第二步:

在所需事务管理的方法上加注解@Transactional


再次运行测试

页面同样报错,但数据库中没有出现任何一条插入信息


注意点:

1.注解需要加在Service的实现中 而不是接口或其他位置

2.不要使用try catch捕获异常  这样将不会进行事务回滚 


若需要捕获异常又需要事务回滚 推荐使用以下方法:

@Transactional
	@Override
	public void add2User()//事务管理测试
	{
        try
        {
        	User user=new User("放得下","mima1","电话1","邮箱1");
        	User user2=new User("放不下放不下放不下放不下放不下放不下放不下放不下",
            		"mima1","电话1","邮箱1");
        	userdao.addUser(user);
        	userdao.addUser(user2);
        }
		catch(Exception e)
		{
			System.out.println("服务器异常");
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
		}
    }

通过


手动回滚

页面不会报错 数据库中也不会多出数据


使用AOP进行事务管理

我们将刚才的@Transactional去除

开始使用AOP方式进行事务管理:

在spring-mybatis的配置文件中加入以下语句:

  <tx:advice id="txAdvice" transaction-manager="transactionManager">
   	<tx:attributes>
   		<tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT"/>
   	</tx:attributes>
   </tx:advice>
   
   <aop:config>
   		<aop:pointcut id="shiwuguanli"
   			expression="execution(* service.UserService.*(..))"/>
   			<aop:advisor advice-ref="txAdvice" pointcut-ref="shiwuguanli"/>
   </aop:config>

其中:


代表“add开头 任意后缀的方法” 我们之前使用的方法是add2User 所以包含在这之中

<tx:method>中的标签有很多

name:方法名的匹配模式,通知根据该模式寻找匹配的方法。 
propagation:设定事务定义所用的传播级别。 
isolation:设置事务的隔离级别。 
timeout:指定事务的超时(秒)。 
read-only:该属性为true指示事务是只读的 
no-rollback-for:以逗号分隔的异常类的列表,目标方法可以跑出这些异常而不会导致通知执行回滚 

rollback-for:以逗号分隔的异常类的列表,当目标方法跑出这些异常时会导致通知执行回滚。默认情况下,该列表为空,因此不在no-rollback-for列表中的任何运行时异常都会导致回滚。 


这里不做详细解释 一般可以采用默认的配置形式


这里表示的是将刚才的txAdvice织入

在调用UserService中所属的所有方法时会调用事务管理 但是要满足上面的name


运行测试成功 页面没有报错信息 数据库中没有插入数据

同时控制台输出了捕获的异常



其他代码:

本文基于之前的各篇SSM学习记录 其他代码没有做出改动 

项目结构如下:


这一个测试中没有创建新的view层页面 仅用浏览器指令完成


总结:

本文仅演示了一种简单的需要事务管理的情景

而事物的四大特征:原子性、一致性、隔离性、持久性

还可以衍生出其他很多种需要事务管理的情况

尤其是隔离性所要求的 本业务的数据不会受到其他业务的干扰 非常重要

具体情况具体分析


谢谢~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值