spring 学习(五):spring 事务

事务概要

一个数据库事务通常包含了一个序列的对数据库的读/写操作。它的存在包含有以下两个目的:

  • 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
  • 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。

所以事务是用来处理异常和并发问题的。

spring 事务管理

spring 的事务管理我们一般采用声明式事务管理这种方式,有两种方式实现:

  • 基于 xml 配置文件实现
  • 基于注解实现

一般使用 PlatformTransactionManager这个事务接口来实现 spring 事务管理。

spring 针对不同的 dao 层框架,提供了接口不同的实现类。

由于现在一般使用 spring JDBC 和 iBatis ,所以我们使用

org.springframework.jdbc.datasource.DataSourceTransactionManager

这个类来实现数据的持久化操作。

spring 实例

我们还是举个栗子来进行 spring 事务操作,以转账操作为例:一人少钱,一人多钱。

1 创建数据库表 account,添加数据,如下图所示:

2 创建 OrdersDao.java 和 OrdersService.java ,实现数据操作:

OrdersDao.java:

package cn.itcast.dao;

import org.springframework.jdbc.core.JdbcTemplate;

public class OrdersDao {
private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
} /*
做对数据库操作的方法,不写业务操作
*/ //少钱的方法
public void lessMoney(){
String sql = "update account set salary=salary+? where username=?";
jdbcTemplate.update(sql, -1000, "小王");
} //多钱的方法
public void moreMoney(){
String sql = "update account set salary=salary+? where username=?";
jdbcTemplate.update(sql, 1000, "小马");
}
}

OrdersService:

package cn.itcast.service;

import cn.itcast.dao.OrdersDao;
import org.springframework.transaction.annotation.Transactional; // @Transactional 使用注解时的操作
public class OrdersService { private OrdersDao ordersDao; public void setOrdersDao(OrdersDao ordersDao) {
this.ordersDao = ordersDao;
} /*
业务逻辑层,写转账业务
调用 dao 方法
*/ public void accountMoney(){
//小王少1000
ordersDao.lessMoney(); int i = 10/0; //抛出异常操作
//小马多1000
ordersDao.moreMoney();
}
}
  • service 层又叫业务逻辑层
  • dao 层,单纯对数据库操作层,在 dao 层不添加业务

我们在编写程序的时候最好按照这种规范操作。

3 创建 applicationContext.xml 文件,完成注入关系,并添加事务模块,出现异常进行回滚操作,配置文件使用 aop 思想配置:

<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 注入属性值 -->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///sampledb"></property>
<property name="user" value="root"></property>
<property name="password" value=""></property>
</bean> <!-- 第一步 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入 dataSource -->
<property name="dataSource" ref="dataSource"> </property>
</bean>
<!-- 第二步 配置事务增强 -->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<!-- 做事务操作 -->
<tx:attributes>
<tx:method name="account*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice> <!-- 第三步 配置切面 -->
<aop:config>
<!-- 切入点 -->
<aop:pointcut id="pointcut1" expression="execution(* cn.itcast.service.OrdersService.*(..))"/>
<!-- 切面 -->
<aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1"/>
</aop:config> <bean id="ordersService" class="cn.itcast.service.OrdersService">
<property name="ordersDao" ref="ordersDao"></property>
</bean>
<bean id="ordersDao" class="cn.itcast.dao.OrdersDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean> </beans>

当然我们还可以采用注解的方式进行事务管理,只需修改配置文件:

<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 注入属性值 -->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///sampledb"></property>
<property name="user" value="root"></property>
<property name="password" value=""></property>
</bean> <!-- 第一步 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 第二步 开启事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/> <bean id="ordersService" class="cn.itcast.service.OrdersService">
<property name="ordersDao" ref="ordersDao"></property>
</bean>
<bean id="ordersDao" class="cn.itcast.dao.OrdersDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean> </beans>

然后在要使用事务的方法所在类上面添加注解 @tTransactional

4 我们编写一个测试类来查看当抛出异常时数据库能不能进行回滚操作。

创建 TestService.java:

package cn.itcast.service;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestService {
@Test
public void testDemo(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
OrdersService ordersService = (OrdersService) context.getBean("ordersService");
ordersService.accountMoney();
}
}

运行测试文件,可以看到在控制台抛出异常:

是因为我们在 OrdersService.java 的 accountMoney() 方法下加入了下面这行:

int i = 10/0;

这是不允许的。查看我们数据库中的数据,可以看到内容没有变,所以是进行了回滚操作的,不然按业务逻辑会出现一方少1000,而另一方内容不变。

spring 学习(五):spring 事务的更多相关文章

  1. Spring学习(十一)-----Spring使用@Required注解依赖检查

    Spring学习(九)-----Spring依赖检查 bean 配置文件用于确定的特定类型(基本,集合或对象)的所有属性被设置.在大多数情况下,你只需要确保特定属性已经设置但不是所有属性.. 对于这种 ...

  2. Spring学习(六)-----Spring使用@Autowired注解自动装配

    Spring使用@Autowired注解自动装配 在上一篇 Spring学习(三)-----Spring自动装配Beans示例中,它会匹配当前Spring容器任何bean的属性自动装配.在大多数情况下 ...

  3. Spring学习(十九)----- Spring的五种事务配置详解

    前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...

  4. spring深入学习(五)-----spring dao、事务管理

    访问数据库基本是所有java web项目必备的,不论是oracle.mysql,或者是nosql,肯定需要和数据库打交道.一开始学java的时候,肯定是以jdbc为基础,如下: private sta ...

  5. spring学习(三) ———— spring事务操作

    前面一篇博文讲解了什么是AOP.学会了写AOP的实现,但是并没有实际运用起来,这一篇博文就算是对AOP技术应用的进阶把,重点是事务的处理. --wh 一.jdbcTemplate 什么是JdbcTem ...

  6. spring学习 8-面试(事务,解决线程安全)

    1.介绍一下Spring的事物管理 参考:Spring 学习7 -事务 2.Spring如何处理线程并发问题    Spring使用ThreadLocal解决线程安全问题 参考:Spring学习11- ...

  7. Spring学习之Spring中AOP方式切入声明式事务

    mybatis-spring官方文档说明 一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中.而不是给 MyBatis 创建一个新的 ...

  8. Spring学习五----------Bean的配置之Bean的生命周期

    © 版权声明:本文为博主原创文章,转载请注明出处 Bean的生命周期 1.定义 2.初始化 3.使用 4.销毁 初始化和销毁的三种方式 1.实现org.springframework.beans.fa ...

  9. Spring学习笔记--spring+mybatis集成

    前言: 技术的发展, 真的是日新月异. 作为javaer, 都不约而同地抛弃裸写jdbc代码, 而用各种持久化框架. 从hibernate, Spring的JDBCTemplate, 到ibatis, ...

  10. spring boot(五)Spring data jpa介绍

    在上篇文章springboot(二):web综合开发中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring data jpa 常见用法以及注意事项 使用spr ...

随机推荐

  1. js的console你知道多少

    js的console你知道多少? 列出所有的console属性 console.dir(console) 或者 console.dirxml(console) 记录代码执行时间 console.tim ...

  2. springboot成神之——Basic Auth应用

    本文介绍Basic Auth在spring中的应用 目录结构 依赖 入口DemoApplication 验证Authenication 配置WebSecurityConfig 控制器TestContr ...

  3. openstack 租户ip 手动配置 openstack静态租户ip

    作者:[吴业亮]云计算开发工程师 博客:http://blog.csdn.net/wylfengyujiancheng 1.综述: 在日常开发和生产环境中经常需要将OpenStack虚拟机配置一个静态 ...

  4. 英语单词state和status的区别

    state:比较常用,各种状态都可以用它,但是它更着重于一种心理状态或者物理状态. Status:用在人的身上一般是其身份和地位,作"状态,情形"讲时,多指政治和商业. state ...

  5. docker 制作本地镜像

    docker commit 55ddf8d62688 py_wb # 容器ID, 容器名称tag py_wb IP地址:5000/my-web:20180511 # 远程registory地址 我的镜 ...

  6. pom.xml配置指定仓库

    <repositories> <repository> <id>central</id><--中央仓库--> <url>http ...

  7. Bell数和Stirling数

    前面说到了Catalan数,现在来了一个Bell数和Stirling数.什么是Bell数,什么是Stirling数呢?两者的关系如何,有用于解决什么算法问题呢? Bell数是以Bell这个人命名的,组 ...

  8. 【总结整理】AXURE原件

    iphone:750*1334 一般用分辨率的一半 移动的时候,按住shift拖动,可水平移动 框选的时候,箭头选择包含模式,只要不全部包含进来,就不会被选中 ctrl+'=显示背景网格 ctrl+s ...

  9. 690. Employee Importance员工权限重要性

    [抄题]: You are given a data structure of employee information, which includes the employee's unique i ...

  10. Django框架 之 querySet详解

    Django框架 之 querySet详解 浏览目录 可切片 可迭代 惰性查询 缓存机制 exists()与iterator()方法 QuerySet 可切片 使用Python 的切片语法来限制查询集 ...