一、Spring 事务

  Spring提供对事务支持的核心包是spring-tx-4.3.6.RELEASE包。

  该包类有三个核心接口,提供对事务的支持:

  1.1PlatformTransactionManager

  该接口是Spring提供的平台管理器,主要用于事务管理。

  该接口提供了如下方法:

  TranscationStatus getTransaction(TransactionDefinition definition);用于获取事务状态信息。

  void commit(TransactionStatus status):提交事务

  void rollback(TransactionStatus status):事务回滚

  此接口的具体实现类:

  org.springframework.jdbc.datasource.DataSourceTransactionManager(用于配置JDBC)。

  1.2TransactionDefinition

  TransactionDefinition是事务定义的对象,包含定义事务规则,获取事务信息等操作。

  String getName();获取事务对象名称。

  int getLsolationLeve();获取事务隔离级别。

  int getPropagationBehavior();获取事务传播行为。

  int getTimeout();获取事务超时时间。

  boolean isReadOnly()判断事务是否只读。

  

  1.3TransactionStatus

  TransactionStatus是事务的状态,包含方法:

  void flush();刷新事务

  boolean isCompleted();判断事务是否完成。

  boolean isNewTranscation();判断是否为新事务。

  boolean isRollbackOnly();判断事务是否回滚。

  void setRollbackOnly:设置事务回滚。

二、声明式事务管理

  声明式事务管理式通过AOP将事务管理作为一个切面,然后将切面(事务管理)织入目标类中。

  先看一个失败案例,未配置事务,进行数据库操作失败情况:

  Account.java

public class Account {
private Integer id;
private String username;
private Double balance; public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Double getBalance() {
return balance;
}
public void setBalance(Double balance) {
this.balance = balance;
} @Override
public String toString() {
return "Account [id=" + id + ", username=" + username + ", balance=" + balance + "]";
} }

AccountDao.java(定义数据库相关操作)

import java.util.List;

public interface AccountDao {
public int addAccount(Account account);
public int updateAccount(Account account);
public int deleteAccount(int id);
public Account findAccountById(int id);
public List<Account> findAllAccounts();
public void transfer(String outUser, String inUser, Double money);//转账
}

AccountDaoImpl.java (AccountDao的实现类)

import java.util.List;

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper; public class AccountDaoImpl implements AccountDao{
private JdbcTemplate jt; public void setJt(JdbcTemplate jt) {
this.jt = jt;
} @Override //添加用户
public int addAccount(Account account) {
String sql = "insert into account(username,balance) value(?,?)";
Object[] obj = new Object[] {
account.getUsername(),
account.getBalance()
};
int num = jt.update(sql,obj);
return num;
} @Override //更新用户
public int updateAccount(Account account) {
String sql = "update account set username=?,balance=?,where id = ?";
Object[] obj = new Object[] {
account.getUsername(),
account.getBalance(),
account.getId()
};
int num = jt.update(sql,obj);
return num;
} @Override //删除用户
public int deleteAccount(int id) {
String sql = "delete from account where id = ?";
int num = jt.update(sql,id);
return num;
} @Override //按ID查找
public Account findAccountById(int id) {
String sql = "select * from account where id = ?";
//设置映射,即表中一行记录对应一个Accout对象(数据库中列名要和对象属性名一致)
RowMapper<Account> rp = new BeanPropertyRowMapper<Account>(Account.class);
return this.jt.queryForObject(sql, rp, id);
} @Override//查找所有对象
public List<Account> findAllAccounts() {
String sql = "select * from account";
RowMapper<Account> rp = new BeanPropertyRowMapper<Account>(Account.class);
return this.jt.query(sql,rp);
} @Override //转账
public void transfer(String outUser, String inUser, Double money) {
//转账
this.jt.update("update account set balance = balance - ?" +
"where username = ?", money, outUser);
int i = 1/0; //模拟意外情况。
//收账
this.jt.update("update account set balance = balance + ?" +
"where username = ?",money,inUser);
}
}

beans.xml

<?xml  version="1.0"  encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd" > <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/spring" />
<property name = "username" value = "root" />
<property name = "password" value = "123456" />
</bean> <bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate">
<property name = "dataSource" ref = "dataSource" />
</bean> <bean id = "accountDao" class = "com.spring.db.AccountDaoImpl">
<property name="jt" ref = "jdbcTemplate"></property>
</bean> </beans>

测试:

  

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate; public class JDBCTemplateTest {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
AccountDao accountDao = (AccountDao)ac.getBean("accountDao");
Account hcf = new Account();
Account zrx = new Account();
//设置两个用户
hcf.setUsername("hcf");
hcf.setBalance(1000.0); zrx.setUsername("zrx");
zrx.setBalance(1000.0);
//将用户添加到数据库
accountDao.addAccount(hcf);
accountDao.addAccount(zrx);
//zrx向hcf转账500
accountDao.transfer("zrx", "hcf", 500.0);
System.out.println("成功");
}
}

转账方法中人为添加一个错误,诸侯出现了转账的金额扣除了,但是收账方没有收到金额。

这种情况显然是我们不允许的。

这时就可以通过事务来实现,把转账功能作为一个事务。

即使中途出现错误没有将钱转给收账方,会发生回滚转账方的钱也不会扣除。

  

  2.1基于XML的声明式事务

  首先我们需要如下jar包:

  

  先了解下xml中配置事务的元素:

  <tx:advice>配置事务通知,

  属性transaction-manager:指定事务管理器。

    <tx:attributes>:<tx:advice>的子元素,用于配置事务细节。

      <tx:method>:<tx:attributes>的子元素,用于配置会务相关信息。

      属性:name:指定与事务关联的方法,可采用通配符*。

         propagation:指定事务传播行为。

         isolation;指定事务隔离级别,默认为REFAULT。

         read-only:指定事务是否只读。

  

  我们只需在benas.xml中配置事务相关信息,然后通过切面的配置,将目标方法织入即可。

<?xml  version="1.0"  encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd" > <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/spring" />
<property name = "username" value = "root" />
<property name = "password" value = "123456" />
</bean> <bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate">
<property name = "dataSource" ref = "dataSource" />
</bean> <bean id = "accountDao" class = "com.spring.db.AccountDaoImpl">
<property name="jt" ref = "jdbcTemplate"></property>
</bean> <!-- 事务管理 -->
<!-- 配置事务管理,并制定数据源 -->
<bean id = "transactionManager"
class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name = "dataSource" ref = "dataSource" />
</bean>
<!-- 配置事务切面,将事务作为一个切面织入方法 -->
<tx:advice id = "txAdvice" transaction-manager = "transactionManager">
<tx:attributes>
<!-- *代表任意方法 传播行为 隔离级别 是否只读 -->
<tx:method name = "*" propagation = "REQUIRED" isolation = "DEFAULT" read-only ="false"/>
</tx:attributes>
</tx:advice> <!-- 配置切面,制定切面,切入点 -->
<aop:config>
<aop:pointcut expression = "execution(* com.spring.db.*.*(..))" id = "txPointCut"/>
<aop:advisor advice-ref = "txAdvice" pointcut-ref = "txPointCut"/>
</aop:config> </beans>

在xml中添加事务配置,我们再来进行转账操作。

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate; public class JDBCTemplateTest {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
AccountDao accountDao = (AccountDao)ac.getBean("accountDao");
Account hcf = new Account();
Account zrx = new Account(); //zrx向hcf转账500
accountDao.transfer("zrx", "hcf", 500.0);
System.out.println("成功");
}
}

再次运行出现错误后数据库中的balance并没有被扣除。

转账和收账作为一个整体,一荣俱荣,一损俱损。

  2.2基于Annotation的声明式事务

    1)在xml中配置事务注解驱动

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

    2)在需要使用事务的类(对类中所有方法有效)或方法(只对方法有效)上添加@Transactional注解。

    

   @Transactional注解属性:

   transactionManager:指定事务管理器。

   isolation:指定事务隔离级。

   noRollbackFor:用于指定遇到异常时强制不执行回滚。

   noRollbackForClassName:指定遇到多个异常时强制不执行回滚。

   该属性可指定多个异常类名。

   propagation:指定事务传播行为。

   read-only:设置事务是否只读,默认为false。

   rollbackFor:用于指定遇到特定异常时强制发生回滚。

   rollbackForClassName:指定遇到多个异常时强制执行回滚。

   timeout:指定事务超时时长。

  beans.xml

  

<?xml  version="1.0"  encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd" > <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/spring" />
<property name = "username" value = "root" />
<property name = "password" value = "123456" />
</bean> <bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate">
<property name = "dataSource" ref = "dataSource" />
</bean> <bean id = "accountDao" class = "com.spring.db.AccountDaoImpl">
<property name="jt" ref = "jdbcTemplate"></property>
</bean> <!-- 事务管理 --> <!-- 配置事务管理,并制定数据源 -->
<bean id = "transactionManager"
class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name = "dataSource" ref = "dataSource" />
</bean>
<!-- 配置事务驱动 -->
<tx:annotation-driven transaction-manager = "transactionManager" /> </beans>

将转账方法加上注解:

@Override //转账
@Transactional(propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT, readOnly = false)
public void transfer(String outUser, String inUser, Double money) {
//转账
this.jt.update("update account set balance = balance - ?" +
"where username = ?", money, outUser);
int i = 1/0; //模拟意外情况。
//收账
this.jt.update("update account set balance = balance + ?" +
"where username = ?",money,inUser);
}

   

1.1(Spring学习笔记)Spring-事务基础的更多相关文章

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

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

  2. Spring学习笔记一:基础概念

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6774310.html    一:Spring是什么 Spring的主要作用是作为对象的容器. 传统编程中,我们 ...

  3. Spring学习笔记--Spring IOC

    沿着我们上一篇的学习笔记,我们继续通过代码学习IOC这一设计思想. 6.Hello类 第一步:首先创建一个类Hello package cn.sxt.bean; public class Hello ...

  4. Spring学习笔记—Spring之旅

    1.Spring简介     Spring是一个开源框架,最早由Rod Johnson创建,并在<Expert One-on-One:J2EE Design and Development> ...

  5. spring学习笔记---数据库事务并发与锁详解

    多事务运行并发问题 在实际应用中,往往是一台(或多台)服务器向无数客户程序提供服务,当服务器查询数据库获取数据时,如果没有采用必要的隔离机制,可能会存在数据库事务的并发问题,下面是一些常见的并发问题分 ...

  6. Spring学习笔记——Spring事务仅仅对执行时异常回滚

    我们在使用Spring时候一般都知道事务在遇到异常的时候会回滚.岂不知Spring的事务默认仅仅有在发生执行时异常即:RunTimeException时才会发生事务,假设一个方法抛出Exception ...

  7. 多事务运行并发问题spring学习笔记——数据库事务并发与锁详解

    多事务运行并发问题 在实际应用中,往往是一台(或多台)服务器向无数客户程序提供服务,当服务器查询数据库获取数据时,如果没有采用必要的隔离机制,可能会存在数据库事务的并发问题,下面是一些常见的并发问题分 ...

  8. 1.4(Spring学习笔记)Spring-JDBC基础

    一.Spring JDBC相关类 1.1 DriverManagerDataSource DriverManagerDataSource主要包含数据库连接地址,用户名,密码. 属性及含义如下配置所示: ...

  9. Spring学习笔记--Spring配置文件和依赖注入

    Spring配置文件 1.alias:设置别名,为bean设置别名,并且可以设置多个别名; <!-- 设置别名 --> <alias name="user" al ...

  10. Spring学习笔记--Spring简介

    1.spring:给软件行业带来了春天; 2.spring的理念:spring框架的初衷是使的现有的更加实用,spring不是创造轮子(技术或框架),而是使现有的轮子更好的运转;spring本身是一个 ...

随机推荐

  1. Qt5 界面中文乱码问题

    1.文件所在项目文件  xxx.pro 中添加: QMAKE_CXXFLAGS += -execution-charset:utf- 2.文件以 UTF-8 编码保存 3.添加  utf-8 BOM

  2. jaspersoft中分组打印

    一:前言 使用IReport已经四个月了,最近在做一个保镖,是要按照类型分类,并且这些类型要横着打印,最后还要算这个类型金额的总值,这张报表现是说需要用到子报表,最后和一个同事一起用group来分组做 ...

  3. swift方法 的写法,ui上拖拽的控件到controller里面的方法

    直接点xcode右上角三个按键中间一下,左右拆分为storyboard和controller, 点击button,按ctrl,然后拖拽到controller里面即可生成对应的点击事件在controll ...

  4. 【洛谷 P4555】 [国家集训队]最长双回文串 (Manacher)

    题目链接 \(|S|<=10^5\),时间还是很宽松的. 允许我们使用线性/\(N\log N\)/甚至\(N \sqrt N\)的算法. 设\(l[i]\)表示以\(a[i]\)结尾的最长回文 ...

  5. 【洛谷 SP2878】Knights of the Round Table(双联通分量)

    先放这吧,没时间写,明天再补 "明天到了" 题目链接 题意:求不在任何奇环内的点的数量. Tarjan求点双联通分量,然后再染色判断是不是二分图就好了. 只是不懂为什么Tarjan ...

  6. DP+贪心水题合集_C++

    本文含有原创题,涉及版权利益问题,严禁转载,违者追究法律责任 本次是最后一篇免费的考试题解,以后的考试题目以及题解将会以付费的方式阅读,题目质量可以拿本次作为参考 本来半个月前就已经搞得差不多了,然后 ...

  7. [bzoj3990][SDOI2015]排序-搜索

    Brief Description 小A有一个1-2^N的排列A[1..2^N],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1<=i<= ...

  8. cve-2012-5613 mysql本地提权

    cve-2012-5613  是一个通过FILE权限写Trigger的TRG存储文件(即伪造Trigger),由root触发而导致权限提升的漏洞.不知道为什么这个漏洞一直没修,可能mysql认为这是一 ...

  9. MySQL 之 foreign key

    前段回顾 create table 表名( 字段名1 类型[(宽度) 约束条件], 字段名2 类型[(宽度) 约束条件], 字段名3 类型[(宽度) 约束条件] ); #解释: 类型:使用限制字段必须 ...

  10. AE特效-与MAYA的结合、制作音乐舞蹈太极动作

    http://blog.sina.com.cn/s/blog_a439a2670101fbkk.html AE特效-与MAYA的结合.制作音乐舞蹈太极动作 (2013-07-24 14:44:12) ...