spring声明式事务管理 入门

合集下载

Spring声明式事务详解

Spring声明式事务详解

Spring声明式事务详解Spring 中的事务控制⽅式Spring 的事务控制可以分为编程式事务控制和声明式事务控制编程式开发者直接把事务的代码和业务代码耦合到⼀起,在实际开发中不⽤。

声明式开发者采⽤配置的⽅式来实现的事务控制,业务代码与事务代码实现解耦合,使⽤的API思想。

基于XML的声明式事务控制【重点】在 Spring配置⽂件中声明式的处理事来代替代码式的处理事务。

底层采⽤ AOP 思想来实现的。

声明式事务控制明确事项:核⼼业务代码(⽬标对象)事务增强代码{ Spring已提供事务管理器)切⾯配置步骤分析1.引⼊tx 命名空间2.事务管理器通知配置3.事务管理器AOP配置引⼊依赖坐标<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:aop="/schema/aop"xmlns:tx="/schema/tx"xsi:schemaLocation="/schema/beanshttps:///schema/beans/spring-beans.xsd/schema/contexthttps:///schema/context/spring-context.xsd/schema/aophttps:///schema/aop/spring-aop.xsd/schema/txhttps:///schema/tx/spring-tx.xsd"></beans>基于 XML 的声明式事务的控制配置⽂件<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:aop="/schema/aop"xmlns:tx="/schema/tx"xsi:schemaLocation="/schema/beanshttps:///schema/beans/spring-beans.xsd/schema/contexthttps:///schema/context/spring-context.xsd/schema/aophttps:///schema/aop/spring-aop.xsd/schema/txhttps:///schema/tx/spring-tx.xsd"><!-- 开启 IOC 注解扫描 --><context:component-scan base-package="inly"/><!-- 引⼊ properties ⽂件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置数据源 --><bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${ername}"/><property name="password" value="${jdbc.password}"/></bean><!-- jdbcTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!-- 绑定数据源 --><property name="dataSource" ref="datasource"/></bean><!-- 事务管理器对象 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 数据源对象 --><property name="dataSource" ref="datasource"/></bean><!-- 通知增强 transaction-manager: 配置的事务管理器对象 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><!-- 定义⼀些事务属性 --><tx:attributes><!-- * 表⽰当前任意名称的⽅法都⾛默认的配置 --><tx:method name="*"/></tx:attributes></tx:advice><!-- AOP 配置切⾯ --><aop:config><!-- 配置声明式式务 --><aop:advisor advice-ref="txAdvice" pointcut="execution(* erServiceImpl.updateUser(..))"/></aop:config></beans>Service 层@Overridepublic void updateUser() {User user = userDao.find(2);user.setName("li3");userDao.updateUser(user);int i = 1 / 0;user.setAge(13);userDao.updateUser(user);System.out.println(user);}事务参数的配置详解<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" timeout="-1" read-only="false"/> name:切点⽅法等isolation:事务的隔离级别propogation:事务的传播⾏为timeout:超时时间read-only:是否只读常⽤ CURD 配置<tx:advice id="txAdvice" transaction-manager="transactionManager"><!-- 定义⼀些事务属性 --><tx:attributes><!-- CRUD 常⽤配置表⽰以update开头的⽅法--><tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" timeout="-1"/> <tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" timeout="-1"/><tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" timeout="-1"/> <tx:method name="find" read-only="true"/><!-- * 表⽰当前任意名称的⽅法都⾛默认的配置 --><tx:method name="*"/></tx:attributes></tx:advice>基于注解的声明式事务控制常⽤注解步骤分析修改 Service 层,增加事务注解@Override@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ,readOnly = false,timeout = -1) public void updateUser() {User user = userDao.find(2);user.setName("li3");userDao.updateUser(user);int i = 1 / 0;user.setAge(13);userDao.updateUser(user);System.out.println(user);}修改 Spring 核⼼配置⽂件,开启事务注解⽀持<tx:annotation-driven/>。

spring的声明式事务和编程式事务

spring的声明式事务和编程式事务

spring的声明式事务和编程式事务事务管理对于企业应⽤来说是⾄关重要的,当出现异常情况时,它可以保证数据的⼀致性.Spring事务管理的两种⽅式1.编程式事务使⽤Transaction Ttempleate或者直接使⽤底层的Platform TransactionManager.对于编程式事务管理,spring推荐使⽤Transaction Template 简单的说就是在代码中需要直接加⼊处理事务的逻辑,可能需要在代码中显式调⽤begin Transaction() commit(). rollback() 等事务管理相关的⽅法,如在执⾏a⽅法的时候需要事务处理,你需要在a⽅法开始时候开启事务,处理完成之后,在⽅法结束的时候,关闭事务.2.声明式事务建⽴在AOP之上的,其本质是对⽅法前后进⾏拦截,然后在⽬标⽅法开始之前创建或者加⼊⼀个事务,在执⾏完⽬标⽅法之后根据执⾏情况提交或者回滚事务,声明式事务最⼤的优点就是不需要通过编程的⽅式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需要在配置⽂件中做相关的事务规则声明(或通过基于@Transaction注解的⽅式),便可以将事务规则应⽤到业务逻辑中. 显然声明式事务管理要优于编程式事务管理,这正是spring倡导的⾮侵⼊式的开发⽅式.声明式事务管理使业务代码不受污染,⼀个普通的POJO对象,只要加上注解就可以获得完全的事务⽀持.和编程式事务相⽐,声明式事务唯⼀不⾜的地⽅是,它的最细粒度只能作⽤到⽅法级别,⽆法做到像编程式事务那样可以作⽤到代码块级别.但是即便有这样的需求,也存在很多变通的⽅法,⽐如,可以将需要进⾏事务管理的代码块独⽴为⽅法等等. 声明式事务管理也有两种常⽤的⽅式,⼀种是基于tx和aop名字的xml配置⽂件,另⼀种就是基于@Transaction注解.显然基于注解的⽅式更简易.更清爽.以Mybatis为例,基于注解的声明式事务配置 1.添加tx名字空间xmlns:tx="/schema/tx"2.开启事务的注解⽀持<!-- 开启事务控制的注解⽀持 --><tx:annotation-driven transaction-manager="transactionManager"/>3、MyBatis⾃动参与到spring事务管理中,⽆需额外配置,只要org.mybatis.spring.SqlSessionFactoryBean引⽤的数据源与DataSourceTransactionManager引⽤的数据源⼀致即可。

全面分析Spring的编程式事务管理及声明式事务管理

全面分析Spring的编程式事务管理及声明式事务管理

开始之前关于本教程本教程将深入讲解Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务。

通过对本教程的学习,您将能够理解Spring 事务管理的本质,并灵活运用之。

先决条件本教程假定您已经掌握了Java 基础知识,并对Spring 有一定了解。

您还需要具备基本的事务管理的知识,比如:事务的定义,隔离级别的概念,等等。

本文将直接使用这些概念而不做详细解释。

另外,您最好掌握数据库的基础知识,虽然这不是必须。

系统需求要试验这份教程中的工具和示例,硬件配置需求为:至少带有512MB 内存(推荐1GB)的系统。

需要安装以下软件:∙Sun JDK 5.0 或更新版本或IBM Developer Kit for the Java 5 platform 版本。

∙Spring framework 2.5。

本教程附带的示例代码已经在Spring 2.5.6 上测试过。

∙MySQL 5.0 或更新版本。

Spring 事务属性分析事务管理对于企业应用而言至关重要。

它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性。

就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作过程中机器突然出故障的情况,此时,事务就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过取款机一样,以保证用户和银行的利益都不受损失。

在Spring 中,事务是通过TransactionDefinition 接口来定义的。

该接口包含与事务属性有关的方法。

具体如清单1所示:清单1. TransactionDefinition 接口中定义的主要方法public interface TransactionDefinition{int getIsolationLevel();int getPropagationBehavior();int getTimeout();boolean isReadOnly();}也许你会奇怪,为什么接口只提供了获取属性的方法,而没有提供相关设置属性的方法。

Spring-事务管理(使用注解方式实现声明式事务管理)

Spring-事务管理(使用注解方式实现声明式事务管理)

Spring-事务管理(使⽤注解⽅式实现声明式事务管理)1.在spring配置⽂件中,配置事务管理器2.在spring配置⽂件中,开启事务注解(1)引⼊名称空间tx(2)开启事务注解3.在service类上⾯(获取service类⾥⾯⽅法上⾯),添加事务注解@Transactional(1)@Transactional,这个注解可以添加到类上⾯,也可以添加到⽅法上⾯(2)如果把这个类添加到类上⾯,这个类⾥⾯所有的⽅法都添加事务(3)如果把这个注解添加到⽅法上⾯,为这个⽅法添加事务<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:p="/schema/p"xmlns:tx="/schema/tx"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd/schema/tx/schema/tx/spring-tx.xsd/schema/context/schema/context/spring-context.xsd"><!-- 开启组件扫描--><context:component-scan base-package="com.orzjiangxiaoyu.spring"></context:component-scan><!-- 数据库连接池 --><context:property-placeholder location="mysqljdbc.properties"></context:property-placeholder><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="${jdbc.url}"></property><property name="username" value="${ername}"></property><property name="password" value="${jdbc.password}"></property><property name="driverClassName" value="${jdbc.driverClassName}"></property></bean><!-- JdbcTemplate对象 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" ><!-- 注⼊dataSource --><property name="dataSource" ref="dataSource"></property></bean><!-- 创建事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 注⼊dataSource --><property name="dataSource" ref="dataSource"></property></bean><!-- 开启事务注解 --><tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven></beans>package com.orzjiangxiaoyu.spring.service;import com.orzjiangxiaoyu.spring.dao.BankDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Isolation;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;/*** @author orz* @create 2020-08-18 16:32*/@Service@Transactional//添加事务注解public class BankService {@Autowiredprivate BankDao bankDao;//转账⽅法//声明式public void accountMoney(){//少钱操作bankDao.reduceMoney();//⼿动抛出异常System.out.println(1/0);//多钱操作bankDao.addMoney();}}测试package com.orzjiangxiaoyu.spring.testdemo;import com.orzjiangxiaoyu.spring.service.BankService;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.transaction.PlatformTransactionManager;/*** @author orz* @create 2020-08-18 16:49*/public class Test1 {@Testpublic void test1(){ApplicationContext context=new ClassPathXmlApplicationContext("jdbcbean.xml"); BankService bankService = context.getBean("bankService", BankService.class); bankService.accountMoney();}}。

关于Spring中声明式事务的使用详解

关于Spring中声明式事务的使用详解

关于Spring中声明式事务的使⽤详解⽬录⼀、前⾔⼆、回顾JDBC的数据库事务三、数据库事务隔离级别3.1 数据库事务的基本特征3.2 详解数据库隔离级别3.2.1 未提交读3.2.2 读提交3.2.3 可重复读3.2.4 串⾏化3.2.5 各个隔离级别的总结四、数据库事务传播⾏为五、Spring中的声明式事务的使⽤5.1 @Transactional的配置属性5.2 Spring的事务管理器5.3 配置事务的传播⾏为和隔离级别六、总结⼀、前⾔在Spring中,数据库事务是通过AOP技术来提供服务的。

使⽤原⽣的JDBC操作时会存在⼤量的try{}catch{}finally{}语句,所以会存在⼤量的冗余代码,例如打开和关闭数据库连接和数据库事务回滚等。

通过Spring的AOP之后,这些冗余的代码就都被处理了。

⼆、回顾JDBC的数据库事务接下来我们⼀起回顾⼀下,刚⼊门使⽤JDBC操作的时候,写得让⼈烦躁代码⽚段吧。

@Servicepublic class JdbcTransaction {@Autowiredprivate DataSource dataSource;public int insertStudent(Student student) {Connection connection = null;int result = 0;try {// 获取数据连接connection = dataSource.getConnection();// 开始事务connection.setAutoCommit(false);// 设置隔离级别connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);// 执⾏sqlPreparedStatement prepareStatement = connection.prepareStatement("insert into t_student(name,gender,age) values (?,?,?)");prepareStatement.setString(1, student.getName());prepareStatement.setString(2, student.getGender());prepareStatement.setInt(3, student.getAge());result = prepareStatement.executeUpdate();// 提交事务mit();} catch (Exception e1) {if (connection != null) {try {// 事务回滚connection.rollback();} catch (Exception e2) {e2.printStackTrace();}}e1.printStackTrace();} finally {try {if (connection != null && !connection.isClosed()) {// 关闭连接connection.close();}} catch (SQLException e) {e.printStackTrace();}}return result;}}在上述的⼀⼤串代码中也就⼀下已⾏的业务代码是我们最为关注的,在每个使⽤JDBC的业务代码中,都经常可以看到数据库连接的获取和关闭以及事务的提交和回滚,⼤量的try...catch...finally..语句会充斥在代码块中。

在Spring中实现声明控制的事务管理(3Eclipse)

在Spring中实现声明控制的事务管理(3Eclipse)

在Eclipse中实现Spring中声明控制的事务管理1、实现Spring的声明控制的事务管理(1)声明控制的事务管理的实现----借助于Spring IoC和AOPSpring提供声明控制的事务管理,这是借助于Spring IoC和AOP所提供的功能,同时提供了TransactionInterceptor拦截器和常用的代理类TransactionProxyFactoryBean,可以直接对组件进行事务代理。

(2)尽量使用声明控制的事务管理不过现在我们不必太理会Spring AOP的编程实现,而只需要进行基本的配置,我们就可以使用声明控制的事务管理。

建议在基于Spring Framework的应用开发中,尽量使用声明控制的事务管理,以获得数据逻辑代码的最佳可读性。

(3)所需要的*.jar包文件---应该加入到系统中Spring的事务管理依赖于aopalliance.jar与cglib-nodep-2.1_3.jar。

因此,我们必须在Web应用的lib目录下增加对aopalliance.jar(在spring-framework-1.2.6\lib\aopalliance目录内)与对cglib-nodep-2.1_3.jar的引用(在spring-framework-1.2.6\lib\cglib目录内)。

将它们加入到我们的lib目录中(4)优点----实现类似EJB CMT的特性使用声明控制的事务管理的好处是,事务管理不侵入我们所开发的组件(此时,在DAO类中不再需要对TransactionManager类的对象的引入),具体来说,我们的DAO类不会意识到正在事务管理之中,而且如果我们想要改变事务管理的策略的话,也只需要在定义配置文件中重新组织即可。

2、实现的基本原理Spring 中进行事务管理的通常方式是利用AOP(面向切片编程)的方式,为普通Java类封装事务控制,它是通过动态代理实现的,由于接口是延迟实例化的, Spring在这段时间内通过其拦截器来加载事务管理器。

Spring声明式事务配置管理方法

Spring声明式事务配置管理方法在学习编程的过程中,我觉得不止要获得课本的知识,更多的是通过学习技术知识提高解决问题的能力,这样我们才能走在最前方,更多Java学习,请搜索疯狂Java;事务配置首先在/WEB-INF/applicationContext.xml添加以下内容:class="org.springframework.orm.hibernate3.HibernateTransactionManager">注:这是作为公共使用的事务管理器Bean。

这个会是事先配置好的,不需各个模块各自去配。

下面就开始配置各个模块所必须的部分,在各自的applicationContext-XXX-beans.xml 配置的对于事务管理的详细信息。

首先就是配置事务的传播特性,如下:需要注意的地方:(1) advice(建议)的命名:由于每个模块都会有自己的Advice,所以在命名上需要作出规范,初步的构想就是模块名+Advice(只是一种命名规范)。

(2) tx:attribute标签所配置的是作为事务的方法的命名类型。

如其中*为通配符,即代表以save为开头的所有方法,即表示符合此命名规则的方法作为一个事务。

propagation="REQUIRED"代表支持当前事务,如果当前没有事务,就新建一个事务。

这是最常见的选择。

(3) aop:pointcut标签配置参与事务的类,由于是在Service中进行数据库业务操作,配的应该是包含那些作为事务的方法的Service类。

首先应该特别注意的是id的命名,同样由于每个模块都有自己事务切面,所以我觉得初步的命名规则因为all+模块名+ServiceMethod。

而且每个模块之间不同之处还在于以下一句:expression="execution(* com.test.testAda.test.model.service.*.*(..))"其中第一个*代表返回值,第二*代表service下子包,第三个*代表方法名,“(..)”代表方法参数。

Spring事务管理之声明式事务管理-基于AspectJ的XML方式

Spring事务管理之声明式事务管理-基于AspectJ的XML⽅式© 版权声明:本⽂为博主原创⽂章,转载请注明出处案例 - 利⽤Spring的声明式事务(AspectJ)管理模拟转账过程数据库准备-- 创建表CREATE TABLE `account`(`id` INT NOT NULL AUTO_INCREMENT,`name` VARCHAR(100) NOT NULL,`money` DOUBLE DEFAULT 0,PRIMARY KEY (`id`))ENGINE = INNODB DEFAULT CHARSET = UTF8;-- 初始化数据INSERT INTO account (name, money) VALUES ('张三', 1000);INSERT INTO account (name, money) VALUES ('李四', 1000);INSERT INTO account (name, money) VALUES ('王五', 1000);实例1.项⽬结构2.pom.xml<project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.spring</groupId><artifactId>SpringTransaction-AspectJ</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version><name>SpringTransaction-AspectJ Maven Webapp</name><url></url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>4.3.8.RELEASE</spring.version></properties><dependencies><!-- junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- spring core --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!-- spring dao --><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><!-- spring test --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><!-- C3P0 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version></dependency><!-- MySQL --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.42</version></dependency><!-- AspectJ --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.10</version></dependency></dependencies><build><finalName>SpringTransaction-AspectJ</finalName></build></project>3.AccountDao.javapackage org.spring.dao;/*** 转账操作DAO层接⼝**/public interface AccountDao {/*** 转出** @param out* 转出账户* @param money* 转出⾦额*/void outMoney(String out, double money);/*** 转⼊** @param in* 转⼊账户* @param money* 转⼊⾦额*/void inMoney(String in, double money);}4.AccountDaoImpl.javapackage org.spring.dao.impl;import org.spring.dao.AccountDao;import org.springframework.jdbc.core.support.JdbcDaoSupport;/*** 转账操作DAO层实现类**/public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao { /*** 转出** @param out* 转出账户* @param money* 转出⾦额*/public void outMoney(String out, double money) {String sql = "update account set money = money - ? where name = ?";this.getJdbcTemplate().update(sql, money, out);}/*** 转⼊** @param in* 转⼊账户* @param money* 转⼊⾦额*/public void inMoney(String in, double money) {String sql = "update account set money = money + ? where name = ?";this.getJdbcTemplate().update(sql, money, in);}}5.AccountService.javapackage org.spring.service;/*** 转账操作业务层接⼝**/public interface AccountService {/*** 转账** @param out* 转出账户* @param in* 转⼊账户* @param money* 转账⾦额*/void transfer(String out, String in, double money);}6.AccountServiceImpl.javapackage org.spring.service.impl;import org.spring.dao.AccountDao;import org.spring.service.AccountService;/*** 转账操作业务层实现类**/public class AccountServiceImpl implements AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}/*** 转账*/public void transfer(String out, String in, double money) {accountDao.outMoney(out, money);accountDao.inMoney(in, money);}}7.jdbc.propertiesjdbc.driver=com.mysql.jdbc.Driverername=rootjdbc.password=***jdbc.url=jdbc:mysql:///spring_transaction?useSSL=true&characterEncoding=UTF-88.applicationContext.xml<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:tx="/schema/tx"xmlns:aop="/schema/aop"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd/schema/context/schema/context/spring-context.xsd/schema/tx/schema/tx/spring-tx.xsd/schema/aop/schema/aop/spring-aop.xsd"><!-- 引⼊外部属性⽂件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置C3P0连接池 --><bean id="dataSource" class="boPooledDataSource"><property name="driverClass" value="${jdbc.driver}"/><property name="user" value="${ername}"/><property name="password" value="${jdbc.password}"/><property name="jdbcUrl" value="${jdbc.url}"/></bean><!-- 配置业务类 --><bean id="accountService" class="org.spring.service.impl.AccountServiceImpl"><!-- 注⼊DAO --><property name="accountDao" ref="accountDao"/></bean><!-- 配置DAO类 --><bean id="accountDao" class="org.spring.dao.impl.AccountDaoImpl"><!-- 注⼊数据库连接池 --><property name="dataSource" ref="dataSource"/></bean><!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 注⼊数据库连接池 --><property name="dataSource" ref="dataSource"/></bean><!-- 配置事务的通知 --><tx:advice id="txAdvice"><tx:attributes><tx:method name="transfer" propagation="REQUIRED"/></tx:attributes></tx:advice><!-- 配置切⾯ --><aop:config><!-- 配置切⼊点 --><aop:pointcut expression="execution(* org.spring.service.*+.*(..))" id="pointcut"/><!-- 配置切⾯ --><aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/></aop:config></beans>9.TestAspectJTransaction.javapackage org.spring.test;import javax.annotation.Resource;import org.junit.Test;import org.junit.runner.RunWith;import org.spring.service.AccountService;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:applicationContext.xml")public class TestAspectJTransaction {@Resource(name="accountService")private AccountService accountService;@Testpublic void testTransfer() {accountService.transfer("张三", "李四", 200d);}}10.效果预览 10.1 正常执⾏ 10.2 ⾮正常执⾏(修改AccountServiceImpl.java如下)package org.spring.service.impl;import org.spring.dao.AccountDao;import org.spring.service.AccountService;/*** 转账操作业务层实现类**/public class AccountServiceImpl implements AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}/*** 转账*/public void transfer(String out, String in, double money) {accountDao.outMoney(out, money);int i = 1 / 0;accountDao.inMoney(in, money);}} 结果如下:参考:。

Spring声明式事务

Spring声明式事务Spring框架对事务管理提供了两种⽅式⽀持1> 编程式事务:TransactionTemplate类(推荐使⽤),基于PlatformTransactionManager类来实现事务管理;2> 声明式事务:基于AOP实现(动态代理⽅式织⼊事务、提交/回滚事务),仅仅须要要配置⽂件⾥配置好事务规则(tx及aop配置或使⽤@Transactional注解),注解⽅式开发简洁推荐使⽤。

编程式事务须要⼿⼯处理事务的开启、提交、回滚,加⼤开发⼯作量,事务控制⼒度更细,能够是⽅法中的代码块级(声明式事务也能够通过将代码块独⽴成⽅法实现同样的功能)。

声明式事务是⾮侵⼊式的(普通的java类加上注解就可以获取事务⽀持)。

事务控制最细⼒度是⽅法级别;事务实现机制在beginTransaction阶段(hiberante框架是beginTransaction()。

spring框架是doBegin()),spring底层实现是会将Connection对象的autoCommit设置为false。

取消⾃⼰主动提交。

然后在endTransaction阶段来提交/回滚。

事务隔离级别(与数据库四个级别⼀致)1> TransactionDefinition.ISOLATION_DEFAULT # 这是默认值。

表⽰使⽤底层数据库的默认隔离级别。

⼤部分数据库通常默认是:READ_COMMITTED读已提交。

2> TransactionDefinition.ISOLATION_READ_UNCOMMITTED # ⼀个事务能够读取还有⼀个事务改动但还没有提交的数据。

存在问题:该级别不能防⽌脏读。

不可反复读和幻读,因此⾮常少使⽤该隔离级别。

⽐⽅PostgreSQL实际上并没有此级别。

3> TransactionDefinition.ISOLATION_READ_COMMITTED # ⼀个事务仅仅能读取还有⼀个事务已经提交的数据。

Spring声明式事务管理

Spring声明式事务管理案例分析 本案例是图书管理系统精简部分,在数据库中有3张表。

分别保存图书库存、图书信息和⽤户信息。

下⾯是建表SQL语句 1DROP TABLE IF EXISTS store;2DROP TABLE IF EXISTS book ;3DROP TABLE IF EXISTS user;45-- 图书表6CREATE TABLE book(7 sn VARCHAR(20) PRIMARY KEY , -- 图书编码8 name VARCHAR(20) NOT NULL, -- 图书名称9 price NUMERIC(9,2) NOT NULL-- 图书价格10 );1112-- 仓库表13CREATE TABLE store(14 sn VARCHAR(20), -- 图书编码15 stock INT(9) NOT NULL, -- 图书库存16CONSTRAINT fk_sn FOREIGN KEY (sn) REFERENCES book(sn)17 );1819-- ⽤户表20CREATE TABLE user(21 id INT(11) PRIMARY KEY AUTO_INCREMENT, -- id22 name VARCHAR(20) NOT NULL, -- 姓名23 balance NUMERIC(9,2) NOT NULL DEFAULT0-- 余额24 );2526INSERT INTO book VALUES ('1001','Java从⼊门到精通',100);27INSERT INTO book VALUES ('1002','Spring从⼊门到精通',90);28INSERT INTO book VALUES ('1003','J2EE核⼼框架',80);2930INSERT INTO store VALUES ('1001',50);31INSERT INTO store VALUES ('1002',20);32INSERT INTO store VALUES ('1003',10);3334INSERT INTO user (name,balance) VALUES ('caoyc',150);实体类Book.java1package com.proc.bean;23public class Book {45private String sn;6private String name;7private Double price;89public String getSn() {10return sn;11 }1213public void setSn(String sn) {14this.sn = sn;15 }1617public String getName() {18return name;19 }2021public void setName(String name) { = name;23 }2425public Double getPrice() {26return price;27 }2829public void setPrice(Double price) {30this.price = price;31 }3233public String toString() {34return "Book [sn=" + sn + ", name=" + name + ", price=" + price + "]";35 }3637 }Store.java1package com.proc.bean;23/**仓库类*/4public class Store {56private String sn;7private Integer stock;8public String getSn() {9return sn;10 }11public void setSn(String sn) {12this.sn = sn;13 }14public Integer getStock() {15return stock;16 }17public void setStock(Integer stock) {18this.stock = stock;19 }20 @Override21public String toString() {22return "Store [sn=" + sn + ", stock=" + stock + "]";23 }242526 }User.java1package com.proc.bean;23/**4 * @author caoyc5 *6*/7public class User {89private Integer id;10private String name;11private Double balance;12public Integer getId() {13return id;14 }15public void setId(Integer id) {16this.id = id;17 }18public String getName() {19return name;20 }21public void setName(String name) { = name;23 }24public Double getBalance() {25return balance;26 }27public void setBalance(Double balance) {28this.balance = balance;29 }30 @Override31public String toString() {32return "User [id=" + id + ", name=" + name + ", balance=" + balance33 + "]";34 }353637 }Spring配置信息使⽤db.properties记录数据库配置信息,这样便于后期维护1 er=root2 jdbc.password=1234563 jdbc.driverClass=com.mysql.jdbc.Driver4 jdbc.jdbcUrl=jdbc\:mysql\:///test配置applicationContext.xml信息1<!-- 配置⾃动扫描策略 -->2<context:component-scan base-package="com.proc"/>34<!-- 读取db.properties配置信息 -->5<context:property-placeholder location="classpath:db.properties"/>67<!-- 配置⼀个C3P0数据源 -->8<bean id="dataSource" class="boPooledDataSource">9<property name="user" value="${er}"/>10<property name="password" value="${jdbc.password}"/>11<property name="driverClass" value="${jdbc.driverClass}"/>12<property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>13</bean>1415<!-- 配置⼀个JdbcTemplate,⽤来操作数据库 -->16<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">17<property name="dataSource" ref="dataSource"/>18</bean> 这⾥我们使⽤⾃动扫描策略,使⽤的是C3P0连接池。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

目的和好处
可以使用最简单的解决方案进行事务管理的需 要,把工作量和复杂度降到最低. 注意:Spring不提供高端应用服务器提供的跨越 远程调用的事务上下文传播。如果你需要这些 特性,我们(Rod Jhonson等)推荐你使用EJB。
Spring声明式事务管理

基础配置
TransactionProxyFactoryBean 基本配置模板(参考 Spring 的 JPetStore ) 事务参数配置(*回滚规则)
Spring声明式事务管理

事务划分策略
建议在业务层应用事务,使得业务层可以捕获触发回退 的任何异常,并发出适当的业务级异常. 不希望在数据访问层应用它们,因为会限制数据访问代 码的重用机会,这些代码随事务需求而变化,由于数据访 问代码不实现业务逻辑,而且原子性是业务级的概念,因 此数据访问代码不应该该划定事务的边界.
深入学习资料

<Spring 发行包附带源码及范例> Spring 团队 <Spring2.0-reference> Spring 团队 <Spring 框架高级编程> Rod Johnson <J2EE Devolopment without EJB> Rod Johnson <解惑 spring 嵌套事务> /post/177582
参考资料

<spring2.0-reference> 9章 Spring 团队 <Oracle 10g 编程艺术> 7章,8章 Thomas Kyte <Spring 框架高级编程> 6章 Rod Johnson <J2EE Devolopment without EJB> 9章 Rod Johnson < spring事务探索> /post/6是将数据库从一种一 致状态转变为另一种一致状态.这就是事物的任 务,在数据库中提交工作时,可以确保要么所有 更改都已经保存,要么所有修改都不保存.另外, 还能保证实现了保护数据完整性的各种规则和 检查.
事务基础

事务的特征
ACID 特征 隔离级别
Spring声明式事务管理
Spring 声明式事务入门
前言 事务基础 Spring 的声明式事务管理 参考资料 深入学习资料

前言

编写目的
作为一个引导和大家一起探讨需要事务处理最 简单的 情况. 理解Spring对声明式事务管理的一般技术.

前提
理解事务的一般性概念. 了解 Spring 的基础操作.
事务基础

相关文档
最新文档