一、Spring的事务管理

在Spring中通常可以通过以下三种方式来实现对事务的管理:

  1. 使用Spring的事务代理工厂管理事务
  2. 使用Spring的事务注解管理事务
  3. 使用AspectJ的AOP配置管理事务

二、Spring事务管理API

(1)事务管理接口

1、PlatformTransactionManager接口有2个常用的实现类:

  • DataSourceTransactionManager:使用JDBC或者iBatis进行持久化数据时使用;
  • HibernateTransactionManager:使用Hibernate进行持久化数据时使用。

2、Spring的回滚方式

Spring事务的默认回滚方式是:发生运行时异常时回滚,发生受查异常时提交。不过对于受查异常,也可以手动设置其回滚方式。

(2)事务定义接口

A、5个事务隔离级别

B、定义了7个事务传播行为常量

  • REQUIRE: 指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中,若当前没有事务,则创建一个新事务。这种传播行为也是最常见的选择,也是Spring默认的事务传播方式;
  • SUPPORTS:指定的方法支持支持当前事务,但若当前没有事务,也可以以非事务方式执行;
  • MANDATORY:指定的方法必须在当前事务内执行,若当前没有事务,则直接抛出异常;
  • REQUIRES_NES:总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕;
  • NOT_SUPPORTED:指定的方法不能在事务环境中执行,若当前存在事务,就将当前事务挂起‘
  • NEVER:指定的方法不能在事务环境下执行,若当前存在事务,就直接抛出异常;
  • NESTED:指定的方法必须在事务内执行,若当前存在事务,则在嵌套事务内执行;若当前没有事务,则创建一个新事务;

c、默认事务超时时限

三、程序举例环境搭建

购买股票举例


1、定义实体类及DB表

 public class Account {
private Integer aid;
private String aname;
private double balance;// 余额 public Account() {
super();
} public Account(Integer aid, String aname, double balance) {
super();
this.aid = aid;
this.aname = aname;
this.balance = balance;
} public Integer getAid() {
return aid;
} public void setAid(Integer aid) {
this.aid = aid;
} public String getAname() {
return aname;
} public void setAname(String aname) {
this.aname = aname;
} public double getBalance() {
return balance;
} public void setBalance(double balance) {
this.balance = balance;
} @Override
public String toString() {
return "Account [aid=" + aid + ", aname=" + aname + ", balance=" + balance + "]";
} }

Account

 public class Stock {
private Integer sid;
private String sname;// 股票名称
private int count;// 股票数量 public Stock() {
super();
} public Stock(Integer sid, String sname, int count) {
super();
this.sid = sid;
this.sname = sname;
this.count = count;
} public Integer getSid() {
return sid;
} public void setSid(Integer sid) {
this.sid = sid;
} public String getSname() {
return sname;
} public void setSname(String sname) {
this.sname = sname;
} public int getCount() {
return count;
} public void setCount(int count) {
this.count = count;
} @Override
public String toString() {
return "Stock [sid=" + sid + ", sname=" + sname + ", count=" + count + "]";
} }

Stock

二、定义Service

 public interface IBuyStockService {
void openAccount(String aname,double money);//开用户
void openStock(String sname,int amount); void buyStock(String aname,double money,String sname,int amount) throws BuyStockException;
}

IBuyStockService

 import com.jmu.dao.IAccountDao;
import com.jmu.dao.IStockDao; public class BuyStockService implements IBuyStockService {
private IAccountDao adao;
private IStockDao sdao; public void setAdao(IAccountDao adao) {
this.adao = adao;
} public void setSdao(IStockDao sdao) {
this.sdao = sdao;
} @Override
public void openAccount(String aname, double money) {
// TODO Auto-generated method stub
adao.insertAccount(aname, money);
} @Override
public void openStock(String sname, int amount) {
// TODO Auto-generated method stub
sdao.insertStock(sname, amount);
} @Override
public void buyStock(String aname, double money, String sname, int amount) throws BuyStockException {
// TODO Auto-generated method stub
boolean isBuy = true;
adao.updateAccount(aname, money, isBuy); if (1 == 1) {
throw new BuyStockException("购买股票异常");
}
sdao.updateStock(sname, amount, isBuy); } }

BuyStockService

 public class BuyStockException extends Exception {

     public BuyStockException() {
super();
// TODO Auto-generated constructor stub
} public BuyStockException(String message) {
super(message);
// TODO Auto-generated constructor stub
} }

BuyStockException

三、定义Dao

 public interface IAccountDao {

      void insertAccount(String aname, double money);
void updateAccount(String aname, double money, boolean isBuy); }

IAccountDao

 public interface IStockDao {

     void insertStock(String sname, int amount);
void updateStock(String sname, int amount, boolean isBuy); }

IStockDao

 import org.springframework.jdbc.core.support.JdbcDaoSupport;

 public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {

     @Override
public void insertAccount(String aname, double money) {
// TODO Auto-generated method stub
String sql = "insert into account(aname,balance) values(?,?)";
this.getJdbcTemplate().update(sql, aname, money);
} @Override
public void updateAccount(String aname, double money, boolean isBuy) {
String sql = "update account set balance=balance+? where aname=?";
if (isBuy) {
// TODO Auto-generated method stub
sql = "update account set balance=balance-? where aname=?";
}
this.getJdbcTemplate().update(sql, money,aname);
} }

AccountDaoImpl

 import org.springframework.jdbc.core.support.JdbcDaoSupport;

 public class StockDaoImpl extends JdbcDaoSupport implements IStockDao {

     @Override
public void insertStock(String sname, int amount) {
// TODO Auto-generated method stub
String sql="insert into stock(sname,count) values(?,?)";
this.getJdbcTemplate().update(sql,sname,amount);
} @Override
public void updateStock(String sname, int amount, boolean isBuy) {
// TODO Auto-generated method stub
String sql="update stock set count=count-? where sname=?";
if (isBuy) {
sql="update stock set count=count+? where sname=?";
}
this.getJdbcTemplate().update(sql,amount,sname);
}; }

StockDaoImpl

四、导入Jar包

项目结构


五、使用事务代理管理事务(方法一)

 <?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"
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">
<!-- IoC --> <!--注册数据源:C3P0 -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean> <!-- 注册属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--注册Dao -->
<bean id="accountDao" class="com.jmu.dao.AccountDaoImpl">
<property name="dataSource" ref="myDataSource" /> </bean>
<bean id="stockDao" class="com.jmu.dao.StockDaoImpl">
<property name="dataSource" ref="myDataSource" /> </bean> <!-- 注册Service -->
<bean id="buyStockService" class="com.jmu.service.BuyStockService">
<property name="adao" ref="accountDao" />
<property name="sdao" ref="stockDao"/>
</bean> <!-- AOP -->
<!-- 注册事务管理器 -->
<bean id="myTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"></property>
</bean> <!-- 生成事务代理对象 -->
<bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="myTransactionManager"></property>
<property name="target" ref="buyStockService"></property>
<property name="transactionAttributes">
<props>
<prop key="open*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
<prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-BuyStockException </prop>
<!--
-异常:表示发生指定异常后 回滚 (通常是受查异常)
+异常:表示发生指定异常后提交 (通常是运行时异常)
-->
</props>
</property>
</bean>
</beans>

applicationContext.xml

-异常:表示发生指定异常后 回滚 (通常是受查异常)
+异常:表示发生指定异常后提交 (通常是运行时异常)

<!-- 生成事务代理对象 -->
<bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="myTransactionManager"></property>
<property name="target" ref="buyStockService"></property>
<property name="transactionAttributes">
<props>
<prop key="open*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
<prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-BuyStockException </prop>
<!--
-异常:表示发生指定异常后 回滚 (通常是受查异常)
+异常:表示发生指定异常后提交 (通常是运行时异常)
-->
</props>
</property>
</bean>
 import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.jmu.service.BuyStockException;
import com.jmu.service.IBuyStockService; public class MyTest { private IBuyStockService service; @Before
public void before(){
String resource="applicationContext.xml";
ApplicationContext aContext=new ClassPathXmlApplicationContext(resource);
service=(IBuyStockService)aContext.getBean("serviceProxy");
} @Test
public void test01(){
service.openAccount("张三", 10000);
service.openStock("腾讯", 0); }
@Test
public void test02() throws BuyStockException{
service.buyStock("张三", 2000, "腾讯", 5); } }

MyTest

六、使用注解管理事务(方法二)

Spring配置文件约束

<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- AOP -->
<!-- 注册事务管理器 -->
<bean id="myTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"></property>
</bean> <!-- 注册事务注解驱动 -->
<tx:annotation-driven transaction-manager="myTransactionManager"/>
@Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
@Override
public void openAccount(String aname, double money) {
// TODO Auto-generated method stub
adao.insertAccount(aname, money);
} @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
@Override
public void openStock(String sname, int amount) {
// TODO Auto-generated method stub
sdao.insertStock(sname, amount);
} @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED,rollbackFor=BuyStockException.class)
@Override
public void buyStock(String aname, double money, String sname, int amount) throws BuyStockException {
// TODO Auto-generated method stub
boolean isBuy = true;
adao.updateAccount(aname, money, isBuy); if (1 == 1) {
throw new BuyStockException("购买股票异常");
}
sdao.updateStock(sname, amount, isBuy); }

输出结果:

七、使用AspectJ的AOP配置管理事务(重点)

导入Jar包

<!-- AOP -->
<!-- 注册事务管理器 -->
<bean id="myTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"></property>
</bean> <tx:advice id="txAdvice" transaction-manager="myTransactionManager">
<!--事务属性 -->
<!--将事务属性织入到方法中 -->
<tx:attributes>
<!--这里指定的是为每一个连接点指定所要应用的事务属性 -->
<tx:method name="open*" isolation="DEFAULT" propagation="REQUIRED" />
<tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED"
rollback-for="BuyStockException" />
</tx:attributes>
</tx:advice> <!-- AOP配置 -->
<aop:config>
<!--这里指定的是切入点 -->
<!-- execution(* *..service.*.open*(..)) -->
<aop:pointcut expression="execution(* *..service.*.*(..))"
id="myPoint" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPoint" />
</aop:config>

Spring_Spring与DAO_Spring的事务管理的更多相关文章

  1. Spring基于AOP的事务管理

                                  Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...

  2. spring声明式事务管理总结

    事务配置 首先在/WEB-INF/applicationContext.xml添加以下内容: <!-- 配置事务管理器 --> <bean id="transactionM ...

  3. SpringMVC+MyBatis整合——事务管理

    项目一直没有做事务管理,这几天一直在想着解决这事,今天早上终于解决了.接下来直接上配置步骤. 我们项目采用的基本搭建环境:SpringMVC.MyBatis.Oracle11g.WebLogic10. ...

  4. Spring Boot中的事务管理

    原文  http://blog.didispace.com/springboottransactional/ 什么是事务? 我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步操作的结合 ...

  5. 【Java EE 学习 54】【OA项目第一天】【SSH事务管理不能回滚问题解决】【struts2流程回顾】

    一.SSH整合之后事务问题和总结 1.引入问题:DAO层测试 假设将User对象设置为懒加载模式,在dao层使用load方法. 注意,注释不要放开. 使用如下的代码块进行测试: 会报错:no sess ...

  6. 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】

    一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...

  7. Spring的事务管理

    事务 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性(ACID) 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致 隔离性:一个事务执行的时候,不应该受到其他事务的打扰 ...

  8. ssh简化后之事务管理

    为了能让大家更好的了解,所以今天跟大家分享整个项目.ps:ssh环境的搭建我就不一一讲解了,请大家参考 http://www.cnblogs.com/zczc1996/p/5842367.html. ...

  9. spring事务管理器设计思想(二)

    上文见<spring事务管理器设计思想(一)> 对于第二个问题,涉及到事务的传播级别,定义如下: PROPAGATION_REQUIRED-- 如果当前没有事务,就新建一个事务.这是最常见 ...

随机推荐

  1. robot framework学习笔记之十-模板

    测试模板可以让关键字驱动测试用例转换为数据驱动测试用例.鉴于普通测试用例是由关键字和可能的参 数组成,使用了模板的测试用例只需要定义模板关键字的参数即可

  2. Linux(Ubuntu)新建用户只有一个$问题

    参考自: http://www.cnblogs.com/ylan2009/articles/2321177.html 1.用root登录操作 2.查看/etc/passwd文件中新建用户的权限 有没有 ...

  3. Swift中的Weak Strong Dance

    亲爱的博客园的关注着博主文章的朋友们告诉你们一个很不幸的消息哦, 这篇文章将会是博主在博客园发表的最后一篇文章咯, 因为之后的文章博主只会发布到这里哦 http://daiweilai.github. ...

  4. QuantLib 金融计算——基本组件之 DayCounter 类

    目录 QuantLib 金融计算--基本组件之 DayCounter 类 DayCounter 对象的构造 一些常用的成员函数 如果未做特别说明,文中的程序都是 Python3 代码. QuantLi ...

  5. 【转载】Analysis Service Tabular Model #002 Analysis services 的结构:一种产品 两个模型

    Analysis Service 2012 Architecture – One Product, Two Models 在之前SQL Server 2008 R2 版本中的分析服务实际上只有一个版本 ...

  6. HDU 4508 湫湫系列故事——减肥记I

    原题链接:点击此处 解题思路: 思路与01背包差不多,思路用二维数组表示: dp[i][v]=max{dp[i-1][v-k*b[i]]+k*a[i]|0<=k*b[i]<=v} 其dp( ...

  7. vue-cli3 chainWebpack配置,去除打包后文件的预加载prefetch/preload(已解决)

    //细节配置修改 chainWebpack: config => { console.log(config,'chainWebpack') // 移除 prefetch 插件 config.pl ...

  8. 20190415 踩过的VMware那些坑,安装CentOS 7后无法连网

    前言 从2018年12月解散粤储软件公司开始,到现在已经失业将近5个月了,还欠下了四五十万的债,最近决心转Java开发,学习Spring Boot,期望尽快摆脱困境.清掉欠的那些钱. 因为Spring ...

  9. C# TCPClient简单示例

    示例使用方法参考 示例 以下一个简单的异步事件TCP客户端实现 using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; usi ...

  10. spring boot快速入门 6: 表单验证

    廖师兄源码: https://gitee.com/liaoshixiong/girl 样例:拦截所有未满18岁的女生 第一步:在girl实体类中:添加注解 @Min(value=18 ,message ...