spring事务配置

合集下载

Spring事务管理中@Transactional的参数配置

Spring事务管理中@Transactional的参数配置

Spring事务管理中@Transactional的参数配置Spring作为低侵⼊的Java EE框架之⼀,能够很好地与其他框架进⾏整合,其中Spring与Hibernate的整合实现的事务管理是常⽤的⼀种功能。

所谓事务,就必须具备ACID特性,即原⼦性、⼀致性、隔离性和持久性,在Hibernate的实现中,需要我们编写代码来完成事务的控制⼯作。

未使⽤Spring的事务管理12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public static void main(String[] args) {// Configuration cfg = new Configuration();// cfg.configure();// SessionFactory sf = cfg.buildSessionFactory();//因为在HibernateUtil类中已经有⼀部分封装⼯作,所以以上三⾏注释掉了。

Session s = null;Transaction tx = null;try{Class.forName("com.HibernateUtil");s = HibernateUtil.getSession();tx = s.beginTransaction(); //这⾥开启了事务//事务中所需的⼀系列数据库操作。

mit();} catch(HibernateException e) { //如果出现异常,且事务已经开启,则需要回滚。

if(tx != null)tx.rollback();throw e;} catch(ClassNotFoundException e) {e.printStackTrace();} finally{ //⽆论如何都需要关闭Session。

Spring@Transactional事务机制

Spring@Transactional事务机制

Spring@Transactional事务机制⼏个概念要清楚:事务的传播机制,事务的边界⼯作原理运⾏配置@Transactional注解的测试类的时候,具体会发⽣如下步骤1)事务开始时,通过AOP机制,⽣成⼀个代理connection对象,并将其放⼊DataSource实例的某个与DataSourceTransactionManager相关的某处容器中。

在接下来的整个事务中,客户代码都应该使⽤该connection连接数据库,执⾏所有数据库命令[不使⽤该connection连接数据库执⾏的数据库命令,在本事务回滚的时候得不到回滚]2)事务结束时,回滚在第1步骤中得到的代理connection对象上执⾏的数据库命令,然后关闭该代理connection对象@Transactional不⽣效的情况1. @Transactional 在private ⽅法是不⽣效2. 在同⼀个bean⾥,嵌套的public⽅法@Transactional 也不⽣效解决⽅法简单粗暴,有需要就在调⽤service中就开@Transactional,如果实在不⾏,像⾥⾯有调⽤第三⽅资源,唔想事务开得太久,可以考虑新建另外⼀个service 去开@Transactional。

那么@Transactional如何⼯作?实现了EntityManager接⼝的持久化上下⽂代理并不是声明式事务管理的唯⼀部分,事实上包含三个组成部分:1. EntityManager Proxy本⾝2. 事务的切⾯3. 事务管理器事务的切⾯事务的切⾯是⼀个“around(环绕)”切⾯,在注解的业务⽅法前后都可以被调⽤。

实现切⾯的具体类是TransactionInterceptor。

事务的切⾯有两个主要职责:1. 在’before’时,切⾯提供⼀个调⽤点,来决定被调⽤业务⽅法应该在正在进⾏事务的范围内运⾏,还是开始⼀个新的独⽴事务。

2. 在’after’时,切⾯需要确定事务被提交,回滚或者继续运⾏。

spring成神之路第四十六篇:Spring如何管理多数据源事务?

spring成神之路第四十六篇:Spring如何管理多数据源事务?

spring成神之路第四⼗六篇:Spring如何管理多数据源事务?本篇内容:通过原理和⼤量案例带⼤家吃透Spring多数据源事务。

Spring中通过事务管理器来控制事务,每个数据源都需要指定⼀个事务管理器,如果我们的项⽬中需要操作多个数据库,那么需要我们配置多个数据源,也就需要配置多个数据管理器。

多数据源事务使⽤2个步骤1、为每个数据源定义⼀个事务管理器如下⾯代码,有2个数据源分别连接数据库ds1和ds2,然后为每个数据源定义了1个事务管理器,此时spring容器中有2个数据源和2个事务管理器。

//数据源1@Beanpublic DataSource dataSource1() {org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/ds1?characterEncoding=UTF-8");dataSource.setUsername("root");dataSource.setPassword("root123");dataSource.setInitialSize(5);return dataSource;}//事务管理器1,对应数据源1@Beanpublic PlatformTransactionManager transactionManager1(@Qualifier("dataSource1")DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}//数据源2@Beanpublic DataSource dataSource2() {org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/ds2?characterEncoding=UTF-8");dataSource.setUsername("root");dataSource.setPassword("root123");dataSource.setInitialSize(5);return dataSource;}//事务管理器2,对应数据源2@Beanpublic PlatformTransactionManager transactionManager2(@Qualifier("dataSource2")DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}2、指定事务的管理器bean名称使⽤@Transaction中时,需通过@Transaction注解的value或transactionManager属性指定事务管理器bean名称,如:@Transactional(transactionManager ="transactionManager1", propagation =Propagation.REQUIRED)publicvoid required(String name){this.jdbcTemplate1.update("insert into user1(name) VALUES (?)", name);这⾥补充⼀下,之前我们使⽤@Transactional的时候,并没有通过value或者transactionManager设置事务管理器,这是为什么?这是因为我们在spring容器中只定义了⼀个事务管理器,spring启动事务的时候,默认会按类型在容器中查找事务管理器,刚好容器中只有⼀个,就拿过来⽤了,如果有多个的时候,如果你不指定,spring是不知道具体要⽤哪个事务管理器的。

Spring事务配置的五种方式

Spring事务配置的五种方式

Spring事务原理统观spring事务,围绕着两个核心PlatformTransactionManager和TransactionStatusspring提供了几个关于事务处理的类:TransactionDefinition //事务属性定义TranscationStatus //代表了当前的事务,可以提交,回滚。

PlatformTransactionManager这个是spring提供的用于管理事务的基础接口,其下有一个实现的抽象类AbstractPlatformTransactionManager,我们使用的事务管理类例如DataSourceTransactionManager等都是这个类的子类。

一般事务定义步骤:TransactionDefinition td = new TransactionDefinition();TransactionStatus ts = transactionManager.getTransaction(td);try{ //do sthmit(ts);}catch(Exception e){transactionManager.rollback(ts);}spring提供的事务管理可以分为两类:编程式的和声明式的。

编程式的,比较灵活,但是代码量大,存在重复的代码比较多;声明式的比编程式的更灵活。

编程式主要使用transactionTemplate。

省略了部分的提交,回滚,一系列的事务对象定义,需注入事务管理对象.void add(){transactionTemplate.execute( new TransactionCallback(){pulic Object doInTransaction(TransactionStatus ts){ //do sth}}}声明式:使用TransactionProxyFactoryBean:<bean id="userManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><property name="transactionManager"><ref bean="transactionManager"/></property><property name="target"><ref local="userManagerTarget"/></property><property name="transactionAttributes"><props><prop key="insert*">PROPAGATION_REQUIRED</prop><prop key="update*">PROPAGATION_REQUIRED</prop><prop key="*">PROPAGATION_REQUIRED,readOnly</prop></props></property></bean>围绕Poxy的动态代理能够自动的提交和回滚事务org.springframework.transaction.interceptor.TransactionProxyFactoryBeanPROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。

关于Spring事务的原理,以及在事务内开启线程,连接池耗尽问题.

关于Spring事务的原理,以及在事务内开启线程,连接池耗尽问题.

关于Spring事务的原理,以及在事务内开启线程,连接池耗尽问题.主要以结果为导向解释Spring 事务原理,连接池的消耗,以及事务内开启事务线程要注意的问题.Spring 事务原理这⾥不多说,⽹上⼀搜⼀⼤堆,也就是基于AOP配合ThreadLocal实现.这⾥强调⼀下Spring Aop 以及Spring 注解式注⼊在⾮Spring容器管理的类中是⽆效的.因为Spring Aop是在运⾏时实现字节码增强,字节码增强有多种实现⽅法,请⾃⾏了解,原⽣AspectJ是编译时织⼊,但是需要特定的编译器.语法并没有Spring Aop好理解.先看下Spring的事务传播⾏为类型事务传播⾏为类型说明PROPAGATION_REQUIRED如果当前没有事务,就新建⼀个事务,如果已经存在⼀个事务中,加⼊到这个事务中。

这是最常见的选择。

PROPAGATION_SUPPORTS⽀持当前事务,如果当前没有事务,就以⾮事务⽅式执⾏。

PROPAGATION_MANDATORY使⽤当前的事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED以⾮事务⽅式执⾏操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER以⾮事务⽅式执⾏,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执⾏。

如果当前没有事务,则执⾏与 PROPAGATION_REQUIRED类似的操作。

打开⽇记debug模式,留意控制台输出以下测试为了可读性以及更容易理解全是基于Spring注解式事务,⽽没有配置声明式事务.测试1:可以看见只创建了⼀个SqlSession以及⼀个事务,在⽅法内所有操作都使⽤同⼀个连接,同⼀个事务@RequestMapping(value="/testThreadTx",method = RequestMethod.GET)@Transactional(propagation = Propagation.REQUIRED)public void testThreadTx(){//此⽅法没有事务(当前⽅法是 Propagation.REQUIRED)Quotation quotation = quotationService.findEntityById(new String("1"));//此⽅法没有事务(当前⽅法是 Propagation.REQUIRED)quotationService.updateEntity(quotation);}//查看控制台输出(红字关键部分,第三个查询是更新⽅法内部需要先查询⼀次再更新,可以⽆视)Creating a new SqlSessionRegistering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@230376b4]ansaction(line/:54) -JDBC Connection [1068277098(com.mysql.jdbc.JDBC4Connection@5d92bace)] will be managed by SpringotationMapper.findEntityById(line/:54) -==> Preparing: SELECT * FROM table WHERE id = 1otationMapper.findEntityById(line/:54) -==> Parameters:otationMapper.findEntityById(line/:54) -<== Total: 1Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@230376b4]Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@230376b4] from current transactionReleasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@230376b4]Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@230376b4] from current transactionotationMapper.updateEntity(line/:54) -==> Preparing: update ….. where id = 1otationMapper.updateEntity(line/:54) -==> Parameters:otationMapper.updateEntity(line/:54) -<== Updates: 1Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@230376b4]erOperationLogServiceImpl(line/:41) -请求所⽤时间:207erOperationLogServiceImpl(line/:42) -请求结束*******************************************************************************Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@230376b4]Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@230376b4]Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@230376b4]测试2:不使⽤事务可以看出在⾮事务操作数据库,会使⽤多个连接,⾮常不环保,这⾥给稍微多线程插⼊埋下⼀个陷阱@RequestMapping(value="/testThreadTx",method = RequestMethod.GET)// @Transactional(propagation = Propagation.REQUIRED)public void testThreadTx(){Quotation quotation = quotationService.findEntityById(new String("1"));quotationService.updateEntity(quotation);}//查看控制台输出(红字关键部分,第三个查询是更新⽅法内部需要先查询⼀次再更新,可以⽆视)Creating a new SqlSessionSqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7f7b94f] was not registered for synchronization because synchronizationansaction(line/:54) -JDBC Connection [352410768(com.mysql.jdbc.JDBC4Connection@c63fcb6)] will not be managed by SpringotationMapper.findEntityById(line/:54) -==> Preparing: SELECT * FROM table WHERE id = 1otationMapper.findEntityById(line/:54) -==> Parameters:otationMapper.findEntityById(line/:54) -<== Total: 1Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7f7b94f]Creating a new SqlSessionSqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7a41785a] was not registered for synchronization because synchronizationansaction(line/:54) -JDBC Connection [1615108970(com.mysql.jdbc.JDBC4Connection@38377d86)] will not be managed by SpringotationMapper.findEntityById(line/:54) -==> Preparing: SELECT * FROM table WHERE id = 1otationMapper.findEntityById(line/:54) -==> Parameters:otationMapper.findEntityById(line/:54) -<== Total: 1Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7a41785a]Creating a new SqlSessionSqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@181e5a22] was not registered for synchronization because synchronizationansaction(line/:54) -JDBC Connection [2096339748(com.mysql.jdbc.JDBC4Connection@5d4e9892)] will not be managed by SpringotationMapper.updateEntity(line/:54) -==> Preparing: update …. where id = 1otationMapper.updateEntity(line/:54) -==> Parameters:otationMapper.updateEntity(line/:54) -<== Updates: 1Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@181e5a22]erOperationLogServiceImpl(line/:41) -请求所⽤时间:614erOperationLogServiceImpl(line/:42) -请求结束*******************************************************************************测试3:@RequestMapping(value="/testThreadTx",method = RequestMethod.GET)@Transactional(propagation = Propagation.REQUIRED)public void testThreadTx(){final ExecutorService executorService = Executors.newFixedThreadPool(3);Quotation quotation = quotationService.findEntityById(new String("1"));quotationService.updateEntity(quotation);List<Future<Integer>> futures = new ArrayList<Future<Integer>>(3);for(int i=0;i<3;i++){Callable<Integer> task = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {Quotation quotation = quotationService.findEntityById(new String("1"));quotationService.updateEntity(quotation);return null;}};futures.add(executorService.submit(task));}executorService.shutdown();}//查看控制台输出(红字关键部分,第三个查询是更新⽅法内部需要先查询⼀次再更新,可以⽆视)为了节篇幅,这⾥不贴出控制台数据⼤概就是输出了10个Creating a new SqlSession(⼤概有些同学使⽤了多线程,把线程池耗完了也没弄明⽩原因)外层⽅法启动⼀个,内部3个线程,每个线程3个.⼀共是使⽤了10个连接.为什么?这涉及到ThreadLocal以及线程私有栈的概念.如果Spring 事务使⽤InhertableThreadLocal就可以把连接传到⼦线程,但是为什么Spring不那么⼲呢?因为这样毫⽆意义,如果把同⼀个连接传到⼦线程,那就是SQL操作会串⾏执⾏,那何必还多线程呢?有关于ThreadLocal,InhertableThreadLocal配合线程池的⼀些陷阱请看我另⼀篇⽂章:测试4:既然使⽤同⼀个事务,不能实现并发操作,那么只能折中,在每⼀个线程开启⼀个事务,减少创建更多的连接,执⾏完毕以后可以返回操作成功失败结果,反馈给⽤户@RequestMapping(value="/testThreadTx",method = RequestMethod.GET)// @Transactional(propagation = Propagation.REQUIRED)public void testThreadTx(){ExecutorService executorService = Executors.newFixedThreadPool(3);List<Future<Integer>> futures = new ArrayList<Future<Integer>>(3);for(int i=0;i<3;i++){Callable<Integer> task = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {quotationService.doSomeThing();return null;}};futures.add(executorService.submit(task));}executorService.shutdown();}//封装⼀下@Override@Transactional(propagation =Propagation.REQUIRED)public void doSomeThing(){Quotation quotation = this.findEntityById(new String("1"));this.updateEntity(quotation);}//查看控制台输出,只会创建3个连接,为节省篇幅,这⾥不贴出控制台所有数据Creating a new SqlSessionCreating a new SqlSessionCreating a new SqlSession最后⼩技巧PROPAGATION_NOT_SUPPORTED(仅仅为了让Spring能获取ThreadLocal的connection),如果不使⽤事务,但是同⼀个⽅法多个对数据库操作,那么使⽤这个传播⾏为可以减少消耗数据库连接@RequestMapping(value="/testThreadTx",method = RequestMethod.GET)@Transactional(propagation = Propagation.NOT_SUPPORTED)public void testThreadTx(){Quotation quotation = quotationService.findEntityById(new String("1"));quotation.setStatus(ClassDataManager.STATE_N);quotationService.updateEntity(quotation);}//这样只会创建⼀个SqlSession。

spring,mybatis事务管理配置与@Transactional注解使用[转]

spring,mybatis事务管理配置与@Transactional注解使用[转]

spring,mybatis事务管理配置与@Transactional注解使用[转]spring,mybatis事务管理配置与@Transactional注解使用概述事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。

Spring Framework对事务管理提供了一致的抽象,其特点如下:为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects)支持声明式事务管理,特别是基于注解的声明式事务管理,简单易用提供比其他事务API如JTA更简单的编程式事务管理API与spring数据访问抽象的完美集成事务管理方式spring支持编程式事务管理和声明式事务管理两种方式。

编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。

对于编程式事务管理,spring推荐使用TransactionTemplate。

声明式事务管理建立在AOP之上的。

其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

显然声明式事务管理要优于编程式事务管理,这正是spring 倡导的非侵入式的开发方式。

声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。

和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。

Spring事务read-only到底是怎么回事?

Spring事务read-only到底是怎么回事?

Spring事务read-only到底是怎么回事?Spring的事务经常会有这样的配置:
<tx:method name="search*" read-only="true"/>
或者这样的注记:
@Transactional(readOnly = true)
原因:
“只读事务”并不是⼀个强制选项,它只是⼀个“暗⽰”,提⽰数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作,
那么JDBC驱动程序和数据库就有可能根据这种情况对该事务进⾏⼀些特定的优化,
⽐⽅说不安排相应的数据库锁,以减轻事务对数据库的压⼒,毕竟事务也是要消耗数据库的资源的。

1 readonly并不是所有数据库都⽀持的,不同的数据库下会有不同的结果。

2 设置了readonly后,connection都会被赋予readonly,效果取决于数据库的实现。

3 在ORM中,设置了readonly会赋予⼀些额外的优化,例如在Hibernate中,会被禁⽌flush等。

MyBatis-Spring-TransactionManager事务管理

MyBatis-Spring-TransactionManager事务管理
<bean class="org.apache.ibatis.transaction.managed.ManagedTransactionFactory" />
</property>
</bean>
编程式事务管理
MyBatis 的 SqlSession 提供指定的方法来处理编程式的事务。 但是当使用 MyBatis-Spring 时, bean 将会使用 Spring 管理的 SqlSession 或映射器来注入。 那就是说 Spring 通常是处理 事务的。
一旦事务创建之后,MyBatis-Spring 将会透明的管理事务。在你的 DAO 类中就不需要额 外的代码了。
标准配置
要 开 启 Spring 的 事 务 处 理 , 在 Spring 的 XML 配 置 文 件 中 简 单 创 建 一 个 DataSourceTransactionManager 对象:
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
</bean>
指定的 DataSource 一般可以是你使用 Spring 的任意 JDBC DataSource。这包含了连接 池和通过 JNDI 查找获得的 DataSource。
要注意, 为事务管理器指定的 DataSource 必须和用来创建 SqlSessionFactoryBean 的 是同一个数据源,否则事务管理器就无法工作了。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Spring事务配置的五种方法事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作。

这样可以防止出现脏数据,防止数据库数据出现问题。

开发中为了避免这种情况一般都会进行事务管理。

在JDBC中是通过Connection对象进行事务管理的,默认是自动提交事务,可以手工将自动提交关闭,通过commit方法进行提交,rollback方法进行回滚,如果不提交,则数据不会真正的插入到数据库中。

Hibernate中是通过Transaction进行事务管理,处理方法与JDBC中类似。

Spring不会直接去管理事务,它提供了很多可供选择的事务管理器,将事务委托给JTA或某些特定的平台事务实现. Spring一般是使用TransactionMananger进行管理,可以通过Spring的注入来完成此功能。

针对Spring事务管理总结如下:要想用Spring的事务管理机制,就需要把数据库的连接交给Spring来管理,(JDBC,SESSION道理一样),如果使用Hibernate框架,要把Session交给Spring管理。

在整个Service方法调用中,虽然Sevice调用了多个Dao,但是整个过程中Session只有一个。

也就是说你对数据库的DML操作,都会先保存在这个Session中,包括update,insert,delete。

当发生异常(这个异常可以是数据库的,也可以是程序的),Spring会把这个Session中对应的DML操作回滚。

Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。

DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

具体如下图:步骤:1首先我们需要声明一个Spring的事务管理器和数据源(dataSource Or sessionFactory)2 需要进行的操作对象(Dao)3 根据需要对Dao 添加接口或Servic 注入Dao4 配置事务代理,注意接口和引用类Servic的区别;根据代理机制的不同,总结了五种Spring事务的配置方式,配置文件如下:第一种方式:每个Bean都有一个代理<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:aop="/schema/aop"xsi:schemaLocation="/schema/beans /schema/beans/spring-beans-2.5.xsd/schema/context/schema/context/spring-context-2.5.xsd /schema/aop/schema/aop/spring-aop-2.5.xsd"><beanid="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml"/><property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/></bean><!-- 定义事务管理器(声明式的事务)--><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/></bean><!-- 配置DAO --><bean id="userDaoTarget" class="erDaoImpl"> <property name="sessionFactory" ref="sessionFactory"/></bean><bean id="userDao"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><!-- 配置事务管理器--><property name="transactionManager" ref="transactionManager"/><property name="target" ref="userDaoTarget"/><!-- 指定加入事务--><property name="proxyInterfaces" value="com.bluesky.spring.dao.GeneratorDao"/> <!-- 配置事务属性--><property name="transactionAttributes"><!-- 事务级别--><props><prop key="*">PROPAGATION_REQUIRED</prop></props></property></bean></beans>第二种方式:所有Bean共享一个代理基类<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:aop="/schema/aop"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-2.5.xsd/schema/context/schema/context/spring-context-2.5.xsd/schema/aop/schema/aop/spring-aop-2.5.xsd"><bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml"/><property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/></bean><!-- 定义事务管理器(声明式的事务)--><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"/></bean><!-- 事务代理Bean --><bean id="transactionBase"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"lazy-init="true" abstract="true"><!-- 配置事务管理器--><property name="transactionManager" ref="transactionManager"/><!-- 配置事务属性--><property name="transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED</prop></props></property></bean><!-- 配置DAO --><bean id="userDaoTarget" class="erDaoImpl"> <property name="sessionFactory" ref="sessionFactory"/></bean><bean id="userDao" parent="transactionBase"> <!-- parent 指明加入事务--> <property name="target" ref="userDaoTarget"/></bean></beans>第三种方式:使用拦截器<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:aop="/schema/aop"xsi:schemaLocation="/schema/beans /schema/beans/spring-beans-2.5.xsd/schema/context/schema/context/spring-context-2.5.xsd/schema/aop/schema/aop/spring-aop-2.5.xsd"><bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml"/><property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/></bean><!-- 定义事务管理器(声明式的事务)--><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"/></bean><bean id="transactionInterceptor"class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager"/><!-- 配置事务属性--><property name="transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED</prop></props></property></bean><!-- 自动代理所有符合条件的Bean都加入事务--><beanclass="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"><list><value>*Dao</value></list></property><property name="interceptorNames"><list><value>transactionInterceptor</value></list></property></bean><!-- 配置DAO --><bean id="userDao" class="erDaoImpl"> <property name="sessionFactory" ref="sessionFactory"/></bean></beans>第四种方式:使用tx标签配置的拦截器<?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/beans /schema/beans/spring-beans-2.5.xsd/schema/context/schema/context/spring-context-2.5.xsd/schema/aop/schema/aop/spring-aop-2.5.xsd/schema/tx/schema/tx/spring-tx-2.5.xsd"> <context:annotation-config /><context:component-scan base-package="com.bluesky"/><bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml"/><property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/></bean><!-- 定义事务管理器(声明式的事务)--><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/></bean><tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes><tx:method name="*" propagation="REQUIRED"/></tx:attributes></tx:advice><aop:config><aop:pointcut id="interceptorPointCuts"expression="execution(* com.bluesky.spring.dao.*.*(..))"/> <aop:advisor advice-ref="txAdvice"pointcut-ref="interceptorPointCuts"/></aop:config></beans>第五种方式:全注解<?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/beans /schema/beans/spring-beans-2.5.xsd/schema/context/schema/context/spring-context-2.5.xsd/schema/aop/schema/aop/spring-aop-2.5.xsd/schema/tx/schema/tx/spring-tx-2.5.xsd"><context:annotation-config /><context:component-scan base-package="com.bluesky"/><tx:annotation-driven transaction-manager="transactionManager"/><bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml"/><property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/></bean><!-- 定义事务管理器(声明式的事务)--><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/></bean></beans>此时在DAO上需加上@Transactional注解,如下:package com.bluesky.spring.dao;import java.util.List;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.orm.hibernate3.support.HibernateDaoSupport;import ponent;import er;@Transactional@Component("userDao")public class UserDaoImpl extends HibernateDaoSupport implements UserDao { public List<User> listUsers() {return this.getSession().createQuery("from User").list();}}注意的几点:1 @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.2 默认情况下,一个有事务方法, 遇到RuntiomeException时会回滚 . 遇到受检查的异常是不会回滚的. 要想所有异常都回滚,要加上@Transactional( rollbackFor={Exception.class,其它异常}) .事务属性:1.事务的隔离级别,定义了事务受并发活动的影响程度有如下可选:可以去看spring源码: org.springframework.transaction.annotation.Isolation我的"隔离级别"相关文章有不明白的,可以去看看2. 事务的传播属性定义了关于客户端和被调用方法的事务边界,有如下可选可以去看spring源码: org.springframework.transaction.annotation.Propagation3, 只读特性 .select xxx for update如果事务只进行读取的动作,则可以利用底层数据库在只读操作时发生的一些最佳化动作,由于这个动作利用到数据库在只读的事务操作最佳化,因而必须在事务中才有效,也就是说要搭配传播行为PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED来设置。

相关文档
最新文档