接下来我将给大家介绍spring事务配置的两种方式:

1.基于XML的事务配置。2.基于注解方式的事务配置。

前言:在我们详细介绍spring的两种声明式事务管理之前,我们需要先理解这些概念

1)spring的事务管理是通过Aop的方式来实现;
2)声明式事务是spring对事务管理的最常用的方式,因为这种方式对代码的影响最小,因此也就符合非侵入式的轻量级的容器的概念;
3)我们需要理解事务的概念,这里不再给出详细说明。

正文:

1.基于XMl的事务配置

现在假设我们有这样一个接口:

[java] view plain copy

 
  1. package x.y.service;
  2. public interface FooService {
  3. Foo getFoo(String fooName);
  4. Foo getFoo(String fooName, String barName);
  5. void insertFoo(Foo foo);
  6. void updateFoo(Foo foo);
  7. }
[java] view plain copy

 
  1. </pre>对应于这个接口有一个实现类如下:<pre name="code" class="java">package x.y.service;
  2. public class DefaultFooService implements FooService {
  3. public Foo getFoo(String fooName) {
  4. throw new UnsupportedOperationException();
  5. }
  6. public Foo getFoo(String fooName, String barName) {
  7. throw new UnsupportedOperationException();
  8. }
  9. public void insertFoo(Foo foo) {
  10. throw new UnsupportedOperationException();
  11. }
  12. public void updateFoo(Foo foo) {
  13. throw new UnsupportedOperationException();
  14. }}

注:上述两端代码是对应于业务层的。我们平时配置事务也最好在业务层进行配置。

 
接下来我们看一下spring 的配置文件中需要我们配置什么吧
[html] view plain copy

 
  1. <!-- from the file 'context.xml' -->
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <beans xmlns="http://www.springframework.org/schema/beans"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xmlns:tx="http://www.springframework.org/schema/tx"
  7. xsi:schemaLocation="
  8. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  9. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
  10. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
  11. <!-- 首先我们要把服务对象fooService声明成一个bean -->
  12. <bean id="fooService" class="x.y.service.DefaultFooService"/>
  13. <!-- 然后是声明一个事物建议tx:advice,spring为我们提供了事物的封装,这个就是封装在了<tx:advice/>中 -->
  14. <!-- <tx:advice/>有一个transaction-manager属性,我们可以用它来指定我们的事物由谁来管理。 -->
  15. <tx:advice id="txAdvice" transaction-manager="txManager">
  16. <!-- 配置这个事务建议的属性 -->
  17. <tx:attributes>
  18. <!-- 指定所有get开头的方法执行在只读事务上下文中 -->
  19. <tx:method name="get*" read-only="true"/>
  20. <!-- 其余方法执行在默认的读写上下文中 -->
  21. <tx:method name="*"/>
  22. </tx:attributes>
  23. </tx:advice>
  24. <!-- 我们定义一个切面,它匹配FooService接口定义的所有操作 -->
  25. <aop:config>
  26. <!-- <aop:pointcut/>元素定义AspectJ的切面表示法,这里是表示x.y.service.FooService包下的任意方法。 -->
  27. <aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
  28. <!-- 然后我们用一个通知器:<aop:advisor/>把这个切面和tx:advice绑定在一起,表示当这个切面:fooServiceOperation执行时tx:advice定义的通知逻辑将被执行 -->
  29. <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
  30. </aop:config>
  31. <!-- 数据元信息 -->
  32. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  33. <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
  34. <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>
  35. <property name="username" value="scott"/>
  36. <property name="password" value="tiger"/>
  37. </bean>
  38. <!-- 管理事务的类-->
  39. <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  40. <property name="dataSource" ref="dataSource"/>
  41. </bean>
  42. <!-- other <bean/> definitions here -->
  43. </beans>
 

现在我通俗的把上面的配置讲解一下:

首先我们应该要把服务对象'fooService' 声明成一个bean,我们要把一个服务对象('fooService' bean)做成事务性的。
我们就应该首先在声明一个事务管理的建议,用什么来管理,spring给我们提供了事务封装,这个就封装在了<tx:advice/>中,
这个事务建议给我们提供了一个transaction-manager属性,用他可以指定我们用谁来管理我们的事务。我们上边的例子用的
为一个指向 PlatformTransactionManager bean的名字(这里指 'txManager'), 该bean将会真正管理事务。上面用的事务
管理类是用的jdbc中提供的事务管理,当然这里也可以指定为hibernate管理。当然了,不管用那个类来管理我们的事务,都
不要忘记了提供我们的datasource属性,因为事务管理也需要这里面的信息。我们声明好事务建议,也指定好了具体用哪个
类来管理了,下面我们的任务就是要把我们定义好的这些利用AOP把我们的事务管理织入到我们的业务逻辑里面了。
<aop:config/> 的定义, 它确保由 'txAdvice'  bean定义的事务通知在应用中合适的点被执行。 
首先我们定义了 一个切面,它匹配 FooService 接口定义的所有操作, 
我们把该切面叫做 'fooServiceOperation'。<aop:pointcut/> 元素定义是AspectJ的切面表示法,
上述表示x.y.service.FooService包下的任意方法。然后我们用一个通知器(advisor)把这个切面与 'txAdvice' 绑定在一起,
 表示当 'fooServiceOperation' 执行时,'txAdvice' 定义的通知逻辑将被执行。大体流程就是这样的了。

<tx:advice/> 有关的设置

通过 <tx:advice/> 标签来指定不同的事务性设置。默认的 <tx:advice/> 设置如下:

事务传播设置是 REQUIRED

隔离级别是DEFAULT

事务是 读/写

事务超时默认是依赖于事务系统的,或者事务超时没有被支持。

任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚

这些默认的设置当然也是可以被改变的。 <tx:advice/> 和 <tx:attributes/> 标签里的 <tx:method/> 各种属性设置总结如下:

Table 9.1. <tx:method/> 有关的设置

属性

是否需要?

默认值

描述

name

 

与事务属性关联的方法名。通配符(*)可以用来指定一批关联到相同的事务属性的方法。 如:'get*'、'handle*'、'on*Event'等等。

propagation

REQUIRED

事务传播行为

isolation

DEFAULT

事务隔离级别

timeout

-1

事务超时的时间(以秒为单位)

read-only

false

事务是否只读?

rollback-for

 

将被触发进行回滚的 Exception(s);以逗号分开。 如:'com.foo.MyBusinessException,ServletException'

no-rollback-for

 

不 被触发进行回滚的 Exception(s);以逗号分开。 如:'com.foo.MyBusinessException,ServletException'

下面我们具体来看一下事务的传播性的几个值:

REQUIRED:业务方法需要在一个容器里运行。如果方法运行时,已经处在一个事务中,那么加入到这个事务,否则自己新建一个新的事务。

NOT_SUPPORTED:声明方法不需要事务。如果方法没有关联到一个事务,容器不会为他开启事务,如果方法在一个事务中被调用,该事务会被挂起,调用结束后,原先的事务会恢复执行。

REQUIRESNEW:不管是否存在事务,该方法总汇为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务挂起,新的事务被创建。

MANDATORY:该方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果在没有事务的环境下被调用,容器抛出例外。

SUPPORTS:该方法在某个事务范围内被调用,则方法成为该事务的一部分。如果方法在该事务范围外被调用,该方法就在没有事务的环境下执行。

NEVER:该方法绝对不能在事务范围内执行。如果在就抛例外。只有该方法没有关联到任何事务,才正常执行。

NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务 拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。

到此为止基于XML的事务配置就算完成了。

使用 @Transactional

除了基于XML文件的声明式事务配置外,你也可以采用基于注解式的事务配置方法。直接在Java源代码中声明事务语义的做法让事务声明和将受其影响的代码距离更近了,而且一般来说不会有不恰当的耦合的风险,因为,使用事务性的代码几乎总是被部署在事务环境中。

下面的例子很好地演示了 @Transactional 注解的易用性,随后解释其中的细节。先看看其中的类定义

[java] view plain copy

 
  1. @Transactional
  2. public class DefaultFooService implements FooService {
  3. Foo getFoo(String fooName);
  4. Foo getFoo(String fooName, String barName);
  5. void insertFoo(Foo foo);
  6. void updateFoo(Foo foo);
  7. }

当我们使用注解式声明事务时,在XML中只需要一句话就ok了

[html] view plain copy

 
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xmlns:tx="http://www.springframework.org/schema/tx"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
  9. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
  10. <bean id="fooService" class="x.y.service.DefaultFooService"/>
  11. <tx:annotation-driven transaction-manager="txManager"/>
  12. <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  13. <property name="dataSource" ref="dataSource"/>
  14. </bean>
  15. </beans>

我们知道 @Transactional 注解可以声明在类上,也可以声明在方法上。在大多数情况下,方法上的事务会首先执行

例如: DefaultFooService 类在类的级别上被注解为只读事务,但是,这个类中的 updateFoo(Foo) 方法的 @Transactional 注解的事务设置将优先于类级别注解的事务设置。

[java] view plain copy

 
  1. @Transactional(readOnly = true)
  2. public class DefaultFooService implements FooService {
  3. public Foo getFoo(String fooName) {
  4. // do something
  5. }
  6. // these settings have precedence for this method
  7. @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
  8. public void updateFoo(Foo foo) {
  9. // do something
  10. }
  11. }

@Transactional 有关的设置

@Transactional 注解是用来指定接口、类或方法必须拥有事务语义的元数据。 如:“当一个方法开始调用时就开启一个新的只读事务,并停止掉任何现存的事务”。 默认的 @Transactional 设置如下:

事务传播设置是 PROPAGATION_REQUIRED

事务隔离级别是 ISOLATION_DEFAULT

事务是 读/写

事务超时默认是依赖于事务系统的,或者事务超时没有被支持。

任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚

这些默认的设置当然也是可以被改变的。 @Transactional 注解的各种属性设置总结如下:

@Transactional 注解的属性

属性

类型

描述

propagation

枚举型:Propagation

可选的传播性设置

isolation

枚举型:Isolation

可选的隔离性级别(默认值:ISOLATION_DEFAULT)

readOnly

布尔型

读写型事务 vs. 只读型事务

timeout

int型(以秒为单位)

事务超时

rollbackFor

一组 Class 类的实例,必须是Throwable 的子类

一组异常类,遇到时 必须 进行回滚。默认情况下checked exceptions不进行回滚,仅unchecked exceptions(即RuntimeException的子类)才进行事务回滚。

rollbackForClassname

一组 Class 类的名字,必须是Throwable的子类

一组异常类名,遇到时 必须 进行回滚

noRollbackFor

一组 Class 类的实例,必须是Throwable 的子类

一组异常类,遇到时 必须不 回滚。

noRollbackForClassname

一组 Class 类的名字,必须是Throwable 的子类

一组异常类,遇到时 必须不 回滚

在写代码的时候,不可能对事务的名字有个很清晰的认识,这里的名字是指会在事务监视器(比如WebLogic的事务管理器)或者日志输出中显示的名字, 对于声明式的事务设置,事务名字总是全限定名+"."+事务通知的类的方法名。比如BusinessService类的handlePayment(..)方法启动了一个事务,事务的名称是:

com.foo.BusinessService.handlePayment

使用 @Transactional

除了基于XML文件的声明式事务配置外,你也可以采用基于注解式的事务配置方法。直接在Java源代码中声明事务语义的做法让事务声明和将受其影响的代码距离更近了,而且一般来说不会有不恰当的耦合的风险,因为,使用事务性的代码几乎总是被部署在事务环境中。

下面的例子很好地演示了 @Transactional 注解的易用性,随后解释其中的细节。先看看其中的类定义

@Transactional 有关的设置

@Transactional 注解是用来指定接口、类或方法必须拥有事务语义的元数据。 如:“当一个方法开始调用时就开启一个新的只读事务,并停止掉任何现存的事务”。 默认的 @Transactional 设置如下:

事务传播设置是 PROPAGATION_REQUIRED

事务隔离级别是 ISOLATION_DEFAULT

事务是 读/写

事务超时默认是依赖于事务系统的,或者事务超时没有被支持。

任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚

这些默认的设置当然也是可以被改变的。 @Transactional 注解的各种属性设置总结如下:

@Transactional 注解的属性

属性

类型

描述

propagation

枚举型:Propagation

可选的传播性设置

isolation

枚举型:Isolation

可选的隔离性级别(默认值:ISOLATION_DEFAULT)

readOnly

布尔型

读写型事务 vs. 只读型事务

timeout

int型(以秒为单位)

事务超时

rollbackFor

一组 Class 类的实例,必须是Throwable 的子类

一组异常类,遇到时 必须 进行回滚。默认情况下checked exceptions不进行回滚,仅unchecked exceptions(即RuntimeException的子类)才进行事务回滚。

rollbackForClassname

一组 Class 类的名字,必须是Throwable的子类

一组异常类名,遇到时 必须 进行回滚

noRollbackFor

一组 Class 类的实例,必须是Throwable 的子类

一组异常类,遇到时 必须不 回滚。

noRollbackForClassname

一组 Class 类的名字,必须是Throwable 的子类

一组异常类,遇到时 必须不 回滚

在写代码的时候,不可能对事务的名字有个很清晰的认识,这里的名字是指会在事务监视器(比如WebLogic的事务管理器)或者日志输出中显示的名字, 对于声明式的事务设置,事务名字总是全限定名+"."+事务通知的类的方法名。比如BusinessService类的handlePayment(..)方法启动了一个事务,事务的名称是:

com.foo.BusinessService.handlePayment

接下来我将给大家介绍spring事务配置的两种方式:

1.基于XML的事务配置。2.基于注解方式的事务配置。

前言:在我们详细介绍spring的两种声明式事务管理之前,我们需要先理解这些概念

1)spring的事务管理是通过Aop的方式来实现;
2)声明式事务是spring对事务管理的最常用的方式,因为这种方式对代码的影响最小,因此也就符合非侵入式的轻量级的容器的概念;
3)我们需要理解事务的概念,这里不再给出详细说明。

正文:

1.基于XMl的事务配置

现在假设我们有这样一个接口:

[java] view plain copy

 
  1. package x.y.service;
  2. public interface FooService {
  3. Foo getFoo(String fooName);
  4. Foo getFoo(String fooName, String barName);
  5. void insertFoo(Foo foo);
  6. void updateFoo(Foo foo);
  7. }
[java] view plain copy

 
  1. </pre>对应于这个接口有一个实现类如下:<pre name="code" class="java">package x.y.service;
  2. public class DefaultFooService implements FooService {
  3. public Foo getFoo(String fooName) {
  4. throw new UnsupportedOperationException();
  5. }
  6. public Foo getFoo(String fooName, String barName) {
  7. throw new UnsupportedOperationException();
  8. }
  9. public void insertFoo(Foo foo) {
  10. throw new UnsupportedOperationException();
  11. }
  12. public void updateFoo(Foo foo) {
  13. throw new UnsupportedOperationException();
  14. }}

注:上述两端代码是对应于业务层的。我们平时配置事务也最好在业务层进行配置。

 
接下来我们看一下spring 的配置文件中需要我们配置什么吧
[html] view plain copy

 
  1. <!-- from the file 'context.xml' -->
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <beans xmlns="http://www.springframework.org/schema/beans"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xmlns:tx="http://www.springframework.org/schema/tx"
  7. xsi:schemaLocation="
  8. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  9. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
  10. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
  11. <!-- 首先我们要把服务对象fooService声明成一个bean -->
  12. <bean id="fooService" class="x.y.service.DefaultFooService"/>
  13. <!-- 然后是声明一个事物建议tx:advice,spring为我们提供了事物的封装,这个就是封装在了<tx:advice/>中 -->
  14. <!-- <tx:advice/>有一个transaction-manager属性,我们可以用它来指定我们的事物由谁来管理。 -->
  15. <tx:advice id="txAdvice" transaction-manager="txManager">
  16. <!-- 配置这个事务建议的属性 -->
  17. <tx:attributes>
  18. <!-- 指定所有get开头的方法执行在只读事务上下文中 -->
  19. <tx:method name="get*" read-only="true"/>
  20. <!-- 其余方法执行在默认的读写上下文中 -->
  21. <tx:method name="*"/>
  22. </tx:attributes>
  23. </tx:advice>
  24. <!-- 我们定义一个切面,它匹配FooService接口定义的所有操作 -->
  25. <aop:config>
  26. <!-- <aop:pointcut/>元素定义AspectJ的切面表示法,这里是表示x.y.service.FooService包下的任意方法。 -->
  27. <aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
  28. <!-- 然后我们用一个通知器:<aop:advisor/>把这个切面和tx:advice绑定在一起,表示当这个切面:fooServiceOperation执行时tx:advice定义的通知逻辑将被执行 -->
  29. <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
  30. </aop:config>
  31. <!-- 数据元信息 -->
  32. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  33. <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
  34. <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>
  35. <property name="username" value="scott"/>
  36. <property name="password" value="tiger"/>
  37. </bean>
  38. <!-- 管理事务的类-->
  39. <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  40. <property name="dataSource" ref="dataSource"/>
  41. </bean>
  42. <!-- other <bean/> definitions here -->
  43. </beans>
 

现在我通俗的把上面的配置讲解一下:

首先我们应该要把服务对象'fooService' 声明成一个bean,我们要把一个服务对象('fooService' bean)做成事务性的。
我们就应该首先在声明一个事务管理的建议,用什么来管理,spring给我们提供了事务封装,这个就封装在了<tx:advice/>中,
这个事务建议给我们提供了一个transaction-manager属性,用他可以指定我们用谁来管理我们的事务。我们上边的例子用的
为一个指向 PlatformTransactionManager bean的名字(这里指 'txManager'), 该bean将会真正管理事务。上面用的事务
管理类是用的jdbc中提供的事务管理,当然这里也可以指定为hibernate管理。当然了,不管用那个类来管理我们的事务,都
不要忘记了提供我们的datasource属性,因为事务管理也需要这里面的信息。我们声明好事务建议,也指定好了具体用哪个
类来管理了,下面我们的任务就是要把我们定义好的这些利用AOP把我们的事务管理织入到我们的业务逻辑里面了。
<aop:config/> 的定义, 它确保由 'txAdvice'  bean定义的事务通知在应用中合适的点被执行。 
首先我们定义了 一个切面,它匹配 FooService 接口定义的所有操作, 
我们把该切面叫做 'fooServiceOperation'。<aop:pointcut/> 元素定义是AspectJ的切面表示法,
上述表示x.y.service.FooService包下的任意方法。然后我们用一个通知器(advisor)把这个切面与 'txAdvice' 绑定在一起,
 表示当 'fooServiceOperation' 执行时,'txAdvice' 定义的通知逻辑将被执行。大体流程就是这样的了。

<tx:advice/> 有关的设置

通过 <tx:advice/> 标签来指定不同的事务性设置。默认的 <tx:advice/> 设置如下:

事务传播设置是 REQUIRED

隔离级别是DEFAULT

事务是 读/写

事务超时默认是依赖于事务系统的,或者事务超时没有被支持。

任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚

这些默认的设置当然也是可以被改变的。 <tx:advice/> 和 <tx:attributes/> 标签里的 <tx:method/> 各种属性设置总结如下:

Table 9.1. <tx:method/> 有关的设置

属性

是否需要?

默认值

描述

name

 

与事务属性关联的方法名。通配符(*)可以用来指定一批关联到相同的事务属性的方法。 如:'get*'、'handle*'、'on*Event'等等。

propagation

REQUIRED

事务传播行为

isolation

DEFAULT

事务隔离级别

timeout

-1

事务超时的时间(以秒为单位)

read-only

false

事务是否只读?

rollback-for

 

将被触发进行回滚的 Exception(s);以逗号分开。 如:'com.foo.MyBusinessException,ServletException'

no-rollback-for

 

不 被触发进行回滚的 Exception(s);以逗号分开。 如:'com.foo.MyBusinessException,ServletException'

下面我们具体来看一下事务的传播性的几个值:

REQUIRED:业务方法需要在一个容器里运行。如果方法运行时,已经处在一个事务中,那么加入到这个事务,否则自己新建一个新的事务。

NOT_SUPPORTED:声明方法不需要事务。如果方法没有关联到一个事务,容器不会为他开启事务,如果方法在一个事务中被调用,该事务会被挂起,调用结束后,原先的事务会恢复执行。

REQUIRESNEW:不管是否存在事务,该方法总汇为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务挂起,新的事务被创建。

MANDATORY:该方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果在没有事务的环境下被调用,容器抛出例外。

SUPPORTS:该方法在某个事务范围内被调用,则方法成为该事务的一部分。如果方法在该事务范围外被调用,该方法就在没有事务的环境下执行。

NEVER:该方法绝对不能在事务范围内执行。如果在就抛例外。只有该方法没有关联到任何事务,才正常执行。

NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务 拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。

到此为止基于XML的事务配置就算完成了。

使用 @Transactional

除了基于XML文件的声明式事务配置外,你也可以采用基于注解式的事务配置方法。直接在Java源代码中声明事务语义的做法让事务声明和将受其影响的代码距离更近了,而且一般来说不会有不恰当的耦合的风险,因为,使用事务性的代码几乎总是被部署在事务环境中。

下面的例子很好地演示了 @Transactional 注解的易用性,随后解释其中的细节。先看看其中的类定义

[java] view plain copy

 
  1. @Transactional
  2. public class DefaultFooService implements FooService {
  3. Foo getFoo(String fooName);
  4. Foo getFoo(String fooName, String barName);
  5. void insertFoo(Foo foo);
  6. void updateFoo(Foo foo);
  7. }

当我们使用注解式声明事务时,在XML中只需要一句话就ok了

[html] view plain copy

 
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xmlns:tx="http://www.springframework.org/schema/tx"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
  9. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
  10. <bean id="fooService" class="x.y.service.DefaultFooService"/>
  11. <tx:annotation-driven transaction-manager="txManager"/>
  12. <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  13. <property name="dataSource" ref="dataSource"/>
  14. </bean>
  15. </beans>

我们知道 @Transactional 注解可以声明在类上,也可以声明在方法上。在大多数情况下,方法上的事务会首先执行

例如: DefaultFooService 类在类的级别上被注解为只读事务,但是,这个类中的 updateFoo(Foo) 方法的 @Transactional 注解的事务设置将优先于类级别注解的事务设置。

[java] view plain copy

 
  1. @Transactional(readOnly = true)
  2. public class DefaultFooService implements FooService {
  3. public Foo getFoo(String fooName) {
  4. // do something
  5. }
  6. // these settings have precedence for this method
  7. @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
  8. public void updateFoo(Foo foo) {
  9. // do something
  10. }
  11. }

@Transactional 有关的设置

@Transactional 注解是用来指定接口、类或方法必须拥有事务语义的元数据。 如:“当一个方法开始调用时就开启一个新的只读事务,并停止掉任何现存的事务”。 默认的 @Transactional 设置如下:

事务传播设置是 PROPAGATION_REQUIRED

事务隔离级别是 ISOLATION_DEFAULT

事务是 读/写

事务超时默认是依赖于事务系统的,或者事务超时没有被支持。

任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚

这些默认的设置当然也是可以被改变的。 @Transactional 注解的各种属性设置总结如下:

@Transactional 注解的属性

属性

类型

描述

propagation

枚举型:Propagation

可选的传播性设置

isolation

枚举型:Isolation

可选的隔离性级别(默认值:ISOLATION_DEFAULT)

readOnly

布尔型

读写型事务 vs. 只读型事务

timeout

int型(以秒为单位)

事务超时

rollbackFor

一组 Class 类的实例,必须是Throwable 的子类

一组异常类,遇到时 必须 进行回滚。默认情况下checked exceptions不进行回滚,仅unchecked exceptions(即RuntimeException的子类)才进行事务回滚。

rollbackForClassname

一组 Class 类的名字,必须是Throwable的子类

一组异常类名,遇到时 必须 进行回滚

noRollbackFor

一组 Class 类的实例,必须是Throwable 的子类

一组异常类,遇到时 必须不 回滚。

noRollbackForClassname

一组 Class 类的名字,必须是Throwable 的子类

一组异常类,遇到时 必须不 回滚

在写代码的时候,不可能对事务的名字有个很清晰的认识,这里的名字是指会在事务监视器(比如WebLogic的事务管理器)或者日志输出中显示的名字, 对于声明式的事务设置,事务名字总是全限定名+"."+事务通知的类的方法名。比如BusinessService类的handlePayment(..)方法启动了一个事务,事务的名称是:

com.foo.BusinessService.handlePayment

使用 @Transactional

除了基于XML文件的声明式事务配置外,你也可以采用基于注解式的事务配置方法。直接在Java源代码中声明事务语义的做法让事务声明和将受其影响的代码距离更近了,而且一般来说不会有不恰当的耦合的风险,因为,使用事务性的代码几乎总是被部署在事务环境中。

下面的例子很好地演示了 @Transactional 注解的易用性,随后解释其中的细节。先看看其中的类定义

@Transactional 有关的设置

@Transactional 注解是用来指定接口、类或方法必须拥有事务语义的元数据。 如:“当一个方法开始调用时就开启一个新的只读事务,并停止掉任何现存的事务”。 默认的 @Transactional 设置如下:

事务传播设置是 PROPAGATION_REQUIRED

事务隔离级别是 ISOLATION_DEFAULT

事务是 读/写

事务超时默认是依赖于事务系统的,或者事务超时没有被支持。

任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚

这些默认的设置当然也是可以被改变的。 @Transactional 注解的各种属性设置总结如下:

@Transactional 注解的属性

属性

类型

描述

propagation

枚举型:Propagation

可选的传播性设置

isolation

枚举型:Isolation

可选的隔离性级别(默认值:ISOLATION_DEFAULT)

readOnly

布尔型

读写型事务 vs. 只读型事务

timeout

int型(以秒为单位)

事务超时

rollbackFor

一组 Class 类的实例,必须是Throwable 的子类

一组异常类,遇到时 必须 进行回滚。默认情况下checked exceptions不进行回滚,仅unchecked exceptions(即RuntimeException的子类)才进行事务回滚。

rollbackForClassname

一组 Class 类的名字,必须是Throwable的子类

一组异常类名,遇到时 必须 进行回滚

noRollbackFor

一组 Class 类的实例,必须是Throwable 的子类

一组异常类,遇到时 必须不 回滚。

noRollbackForClassname

一组 Class 类的名字,必须是Throwable 的子类

一组异常类,遇到时 必须不 回滚

在写代码的时候,不可能对事务的名字有个很清晰的认识,这里的名字是指会在事务监视器(比如WebLogic的事务管理器)或者日志输出中显示的名字, 对于声明式的事务设置,事务名字总是全限定名+"."+事务通知的类的方法名。比如BusinessService类的handlePayment(..)方法启动了一个事务,事务的名称是:

com.foo.BusinessService.handlePayment

spring对事务的配置的更多相关文章

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

    spring,mybatis事务管理配置与@Transactional注解使用[转] spring,mybatis事务管理配置与@Transactional注解使用 概述事务管理对于企业应用来说是至关 ...

  2. spring,mybatis事务管理配置与@Transactional注解使用

    spring,mybatis事务管理配置与@Transactional注解使用[转]   spring,mybatis事务管理配置与@Transactional注解使用 概述事务管理对于企业应用来说是 ...

  3. SPRING中事务的配置

    采用这种配置策略,完全可以避免增量式配置,所有的事务代理由系统自动创建.容器中的目标bean自动消失,避免需要使用嵌套bean来保证目标bean不可被访问.这 种配置方式依赖于Spring提供的bea ...

  4. spring的事务管理配置

    spring有两种事务配置器,可以使用spring的jdbc事务管理器,也可以使用对hibernate的事务管理器 第一种 使用Spring JDBC或IBatis进行事务配置(配置文件方式): &l ...

  5. spring的事务如何配置

    spring的声明式事务配置: 1. <!-- 配置sessionFactory --> <bean id="sessionFactory" class=&quo ...

  6. spring+ibatis事务管理配置

    <!-- 配置事务管理器 --> <bean id="transactionManager"         class="org.springfram ...

  7. spring框架 事务 注解配置方式

    user=LF password=LF jdbcUrl=jdbc:oracle:thin:@localhost:1521:orcl driverClass=oracle.jdbc.driver.Ora ...

  8. spring框架 事务 xml配置方式

    user=LF password=LF jdbcUrl=jdbc:oracle:thin:@localhost:1521:orcl driverClass=oracle.jdbc.driver.Ora ...

  9. Spring 声明事务中transactionAttributes属性 + - Exception 实现逻辑

    下面是一段典型的Spring 声明事务的配置: <bean id=“baseTxProxy” lazy-init=“true”class=“org.springframework.transac ...

随机推荐

  1. Nextcloud私有云盘在Centos7下的部署笔记

    搭建个人云存储一般会想到ownCloud,堪称是自建云存储服务的经典.而Nextcloud是ownCloud原开发团队打造的号称是“下一代”存储.初一看觉得“口气”不小,刚推出来就重新“定义”了Clo ...

  2. linux-shell-引用-命令替换-命令退出状态-逻辑操作符

    命令替换:bash7步扩展的之一 嵌套  这里没什么意义 退出状态可以参与逻辑判断 表达式 算数表达式和条件表达式,逻辑表达式 查看passwd命令比,避免用户捕获输入密码的接口 这种方式就可以直接输 ...

  3. PairWork-电梯调度程序结对编程

    结对编程人员:050/184 1 结对编程 1.1 结对编程的优缺点 优点: ● 与单独开发相比,结对能够使人们在压力之下保持更好的状态.结对编程鼓励双方保持代码的高质量,即使在出现了让人不得不飞快地 ...

  4. 北航MOOC客户端

    我们的团队作业终于完成了,欢迎下载使用我们的北航MOOC手机客户端软件(Android端)——北航学堂,学习北航的公开课程. 安装包下载地址: http://pan.baidu.com/s/1jGvH ...

  5. Python学习笔记 -- 第五章

    模块 使用模块可以提高了代码的可维护性.其次,编写代码不必从零开始.当一个模块编写完毕,就可以被其他地方引用.我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块: ...

  6. 9-Python3从入门到实战—基础之条件控制语句

    Python从入门到实战系列--目录 条件判断 if 条件判断 if 语句语法 if <条件判断1>: <执行1> elif <条件判断2>: <执行2> ...

  7. Laravel Exception处理逻辑解析

    Laravel Exception处理逻辑解析 vendor/laravel/framework/src/Illuminate/Foundation/Application.php app首先继承了c ...

  8. PAT 1049 数列的片段和

    https://pintia.cn/problem-sets/994805260223102976/problems/994805275792359424 给定一个正数数列,我们可以从中截取任意的连续 ...

  9. SQL 中GO的作用

    use db_CSharp go select *, 备注=case when Grade>= then '成绩优秀' when Grade< and Grade>= then '成 ...

  10. 自定义控件DataPager

    在最近的一个项目中,涉及到一个自定义翻页控制的控件,下面就这一个控件做详细的说明,这个自定义控件的主要作用是对数据源进行翻页控制,比如说:“上一页.下一页.首页.末页”等相关操作,由于在一个项目中有多 ...