Spring编程式事务管理及声明式事务管理

全面分析 Spring 的编程式事务管理及声明式事务管理 NULL 博文链接:https://konglx.iteye.com/blog/1836826 立即下载

Spring 事务属性剖析

事务治理对企业运用而言至关主要。它担保了用户的每次操作都是靠得住的,即便泛起了异常的接见情形,也不至于损坏后台数据的完整性。就像银行的自助 取款机,常日都能正常为客户干事,然则也难免碰着操作进程傍边机械溘然出缺点的情形,此时,事务就必需确保出缺点前对账户的操作不生效,就像用户适才完整 没有行使过取款机一样,以担保用户和银行的优点都不受损丢失落。

在 Spring 中,事务是经由进程 TransactionDefinition 接口来界说的。该接口包括与事务属性有关的方法。具体如清单1所示:

清单1. TransactionDefinition 接口中界说的次要方法
public interface TransactionDefinition{
int getIsolationLevel();
int getPropagationBehavior();
int getTimeout();
boolean isReadOnly();
}

也许你会希奇,为什么接口只供应了获得属性的方法,而没有供应相关设置属性的方法。其实事理很庞杂,事务属性的设置完整是轨范员掌握的,是以轨范员 可以自界说任何设置属性的方法,而且留存属性的字段也没有任何要求。独一的要求的是,Spring 中止事务操作的时辰,经由进程挪用以上接口供给的方法必需可以前旧事务相关的属性取值。

事务隔离级别

隔离级别是指若干个并发的事务之间的隔离水平。TransactionDefinition 接口中界说了五个泄漏表现隔离级其他常量:

  • TransactionDefinition.ISOLATION_DEFAULT:这是默许值,泄漏表现行使底层数据库的默许隔离级别。对除夜部份数据 库而言,常日这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别泄漏表现一个事务可以读取其他一个事务改削但还没有提交的数据。该级别不能避免脏读和弗成重复读,是以很少行使该隔离级别。
  • TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别泄漏表现一个事务只能读取其他一个事务已提交的数据。该级别可以避免脏读,这也是除夜多半情形下的举荐值。
  • TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别泄漏表现一个事务在悉数进程傍边可以多次 重复实行某个查询,而且每次前往的记载都沟通。即便在多次查询之间有新增的数据知足该查询,这些新增的记载也会被疏忽。该级别可以避免脏读和弗成重复读。
  • TransactionDefinition.ISOLATION_SERIALIZABLE:一切的事务顺次一一实行,这样事务之间就完整弗成能发生发火烦扰,也就是说,该级别可以避免脏读、弗成重复读和幻读。然则这将严重影响轨范的功效。常日情形下也不会用到该级别。

事务流传举动

所谓事务的流传举动是指,假定在最先当前事务之前,一个事务高下文已存在,此时有若干选项可以指定一个事务性方法的执步履作。在TransactionDefinition界说中包括了以下几个泄漏表现流传举动的常量:

  • TransactionDefinition.PROPAGATION_REQUIRED:假定当前存在事务,则介入该事务;假定当前没有事务,则树立一个新的事务。
  • TransactionDefinition.PROPAGATION_REQUIRES_NEW:树立一个新的事务,假定当前存在事务,则把当前事务挂起。
  • TransactionDefinition.PROPAGATION_SUPPORTS:假定当前存在事务,则介入该事务;假定当前没有事务,则以非事务的体式格式连续运转。
  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务体式格式运转,假定当前存在事务,则把当前事务挂起。
  • TransactionDefinition.PROPAGATION_NEVER:以非事务体式格式运转,假定当前存在事务,则抛出异常。
  • TransactionDefinition.PROPAGATION_MANDATORY:假定当前存在事务,则介入该事务;假定当前没有事务,则抛出异常。
  • TransactionDefinition.PROPAGATION_NESTED:假定当前存在事务,则树立一个事务作为当前事务的嵌套事务来运转; 假定当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

这里需求指出的是,后面的六种事务流传举动是 Spring 从 EJB 中引入的,他们同享沟通的概念。而 PROPAGATION_NESTED是 Spring 所独有的。以 PROPAGATION_NESTED 启动的事务内嵌于内部事务中(假定存在内部事务的话),此时,内嵌事务并非一个自力的事务,它依托于内部事务的存在,只需经由进程内部的事务提交,才华激 起内部事务的提交,嵌套的子事务不能零丁提交。假定熟习 JDBC 中的留存点(SavePoint)的概念,那嵌套事务就很随意疏忽理解了,其实嵌套的子事务就是留存点的一个运用,一个事务中可以包括多个留存点,每一个 嵌套子事务。其他,内部事务的回滚也会致使嵌套子事务的回滚。

事务超时

所谓事务超时,就是指一个事务所准许实行的最长时辰,假定跨越该时辰限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来泄漏表现超不时辰,其单元是秒。

事务的只读属性

事务的只读属性是指,对事务性成本中止只读操作或是读写操作。所谓事务性成本就是指那些被事务治理的成本,好比数据源、 JMS 成本,和自界说的事务性成本等等。假定一定只对事务性成本中止只读操作,那末我们可以将事务符号为只读的,以提高事务处置责罚的功效。在 TransactionDefinition 中以 boolean 类型来泄漏表现该事务能否是只读。

事务的回滚划定礼貌

常日情形下,假定在事务中抛出了未搜检异常(连续自 RuntimeException 的异常),则默许将回滚事务。假定没有抛出任何异常,或抛出了已搜检异常,则仍然提交事务。这常日也是除夜多半垦荒者进展的处置责罚体式格式,也是 EJB 中的默许处置责罚体式格式。然则,我们可以凭证需求工资掌握事务在抛出某些未搜检异常时任然提交事务,或在抛出某些已搜检异常时回滚事务。


Spring 事务治理 API 剖析

Spring 框架中,触及到事务治理的 API 除夜约有100个旁边,个中最主要的有三个:TransactionDefinition、PlatformTransactionManager、 TransactionStatus。所谓事务治理,其实就是“依照给定的事务划定礼貌来实行提交或回滚操作”。“给定的事务划定礼貌”就是用 TransactionDefinition 泄漏表现的,“依照……来实行提交或回滚操作”就是用 PlatformTransactionManager 来泄漏表现,而 TransactionStatus 用于泄漏表现一个运转着的事务的形态。打一个不适合的歧,TransactionDefinition 与 TransactionStatus 的关系就像轨范和进程的关系。

TransactionDef…

该接口在后面已引见过,它用于界说一个事务。它包括了事务的静态属性,好比:事务流传举动、超不时辰等等。Spring 为我们供应了一个默许的完成类:DefaultTransactionDefinition,该类适用于除夜多半情形。假定该类不能知足需求,可以经由进 程完成 TransactionDefinition 接口来完成本人的事务界说。

PlatformTrans…

PlatformTransactionManager 用于实行具体的事务操作。接口界说如清单2所示:

清单2. PlatformTransactionManager 接口中界说的次要方法
Public interface PlatformTransactionManager{
  TransactionStatus getTransaction(TransactionDefinition definition)
   throws TransactionException;
   void commit(TransactionStatus status)throws TransactionException;
   void rollback(TransactionStatus status)throws TransactionException;
}

凭证底层所行使的不合的经久化 API 或框架,PlatformTransactionManager 的次要完成类除夜致以下:

  • DataSourceTransactionManager:适用于行使JDBC和iBatis中止数据经久化操作的情形。
  • HibernateTransactionManager:适用于行使Hibernate中止数据经久化操作的情形。
  • JpaTransactionManager:适用于行使JPA中止数据经久化操作的情形。
  • 其他还有JtaTransactionManager 、JdoTransactionManager、JmsTransactionManager等等。

假定我们行使JTA中止事务治理,我们可以经由进程 JNDI 和 Spring 的 JtaTransactionManager 来获得一个容器治理的 DataSource。JtaTransactionManager 不需求晓得 DataSource 和其他特定的成本,因为它将行使容器供应的全局事务治理。而对其他事务治理器,好比DataSourceTransactionManager,在界说时 需求供应底层的数据源作为其属性,也就是 DataSource。与 HibernateTransactionManager 对应的是 SessionFactory,与 JpaTransactionManager 对应的是 EntityManagerFactory 等等。

TransactionStatus

PlatformTransactionManager.getTransaction(…) 方法前往一个 TransactionStatus 对象。前往的TransactionStatus 对象可以代表一个新的或已存在的事务(假定在当前挪用客栈有一个相符前提的事务)。TransactionStatus 接口供给了一个庞杂的掌握事务实行和查询事务形态的方法。该接口界说如清单3所示:

清单3. TransactionStatus 接口中界说的次要方法
public  interface TransactionStatus{
   boolean isNewTransaction();
   void setRollbackOnly();
   boolean isRollbackOnly();
}

编程式事务治理

Spring 的编程式事务治理概述

在 Spring 泛起之前,编程式事务治理对基于 POJO 的运用来说是独一选择。用过 Hibernate 的人都晓得,我们需求在代码中显式挪用beginTransaction()、commit()、rollback()等事务治理相关的方法,这就是编程 式事务治理。经由进程 Spring 供应的事务治理 API,我们可以在代码中无邪掌握事务的实行。在底层,Spring 仍然将事务操作请托给底层的经久化框架来实行。

基于底层 API 的编程式事务治理

凭证PlatformTransactionManager、TransactionDefinition 和 TransactionStatus 三个焦点接口,我们完整可以经由进程编程的体式格式来中止事务治理。示例代码如清单4所示:

清单4. 基于底层 API 的事务治理示例代码
public class BankServiceImpl implements BankService {
private BankDao bankDao;
private TransactionDefinition txDefinition;
private PlatformTransactionManager txManager;
......
public boolean transfer(Long fromId, Long toId, double amount) {
TransactionStatus txStatus = txManager.getTransaction(txDefinition);
boolean result = false;
try {
result = bankDao.transfer(fromId, toId, amount);
txManager.commit(txStatus);
} catch (Exception e) {
result = false;
txManager.rollback(txStatus);
System.out.println("Transfer Error!");
}
return result;
}
}

呼应的设置配备铺排文件如清单5所示:

清单5. 基于底层API的事务治理示例设置配备铺排文件
<bean id="bankService" class="footmark.spring.core.tx.programmatic.origin.BankServiceImpl">
<property name="bankDao" ref="bankDao"/>
<property name="txManager" ref="transactionManager"/>
<property name="txDefinition">
<bean class="org.springframework.transaction.support.DefaultTransactionDefinition">
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
</bean>
</property>
</bean>

如上所示,我们在类中增加了两个属性:一个是 TransactionDefinition 类型的属性,它用于界说一个事务;其他一个是 PlatformTransactionManager 类型的属性,用于实行事务治理操作。

假定方法需求实行事务治理,我们首先需求在方法最先实行前启动一个事务,挪用 PlatformTransactionManager.getTransaction(…) 方法即可启动一个事务。树立并启动了事务之后,即可以最先编写营业逻辑代码,然后在适合的地方实行事务的提交或回滚。

基于 TransactionTemplate 的编程式事务治理

经由进程后面的示例可以发明,这类事务治理体式格式很随意疏忽理解,但使人头疼的是,事务治理的代码散落在营业逻辑代码中,损坏了原有代码的条感 性,而且每一个营业方法都包括了相反的启动事务、提交/回滚事务的样板代码。幸而,Spring 也意想到了这些,并供应了简化的方法,这就是 Spring 在数据接见层异经罕有的模板回调方法。如清单6所示:

清单6. 基于 TransactionTemplate 的事务治理示例代码
public class BankServiceImpl implements BankService {
private BankDao bankDao;
private TransactionTemplate transactionTemplate;
......
public boolean transfer(final Long fromId, final Long toId, final double amount) {
return (Boolean) transactionTemplate.execute(new TransactionCallback(){
public Object doInTransaction(TransactionStatus status) {
Object result;
try {
result = bankDao.transfer(fromId, toId, amount);
} catch (Exception e) {
status.setRollbackOnly();
result = false;
System.out.println("Transfer Error!");
}
return result;
}
});
}
}

呼应的XML设置配备铺排以下:

清单 7. 基于 TransactionTemplate 的事务治理示例设置配备铺排文件
<bean id="bankService"
class="footmark.spring.core.tx.programmatic.template.BankServiceImpl">
<property name="bankDao" ref="bankDao"/>
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>

TransactionTemplate 的 execute() 方法有一个 TransactionCallback 类型的参数,该接口中界说了一个 doInTransaction() 方法,常日我们以匿名内部类的体式格式完成 TransactionCallback 接口,并在其 doInTransaction() 方法中书写营业逻辑代码。这里可以行使默许的事务提交和回滚划定礼貌,这样在营业代码中就不需求显式挪用任何事务治理的 API。doInTransaction() 方法有一个TransactionStatus 类型的参数,我们可以在方法的任何位置挪用该参数的 setRollbackOnly() 方法将事务标识为回滚的,以实行事务回滚。

凭证默许划定礼貌,假定在实行回调方法的进程傍边抛出了未搜检异常,或显式挪用了TransacationStatus.setRollbackOnly() 方法,则回滚事务;假定事务实行完成或抛出了 checked 类型的异常,则提交事务。

TransactionCallback 接口有一个子接口 TransactionCallbackWithoutResult,该接口中界说了一个 doInTransactionWithoutResult() 方法,TransactionCallbackWithoutResult 接口次要用于事务进程傍边不需求前往值的情形。虽然,对不需求前往值的情形,我们仍然可以行使 TransactionCallback 接口,并在方法中前往随意率性值即可。


声明式事务治理

Spring 的声明式事务治理概述

Spring 的声明式事务治理在底层是竖立在 AOP 的根蒂根抵之上的。其实质是对方法前落先行隔绝,然后在目的方法最先之前树立或介入一个事务,在实行完目的方法之后凭证实行情形提交或回滚事务。

声明式事务最除夜的优点就是不需求经由进程编程的体式格式治理事务,这样就不需求在营业逻辑代码中搀杂事务治理的代码,只需在设置配备铺排文件中做 相关的事务划定礼貌声明(或经由进程等价的基于标注的体式格式),即可以将事务划定礼貌运用到营业逻辑中。因为事务治理本人就是一个范例的横切逻辑,恰是 AOP 的用武之地。Spring 垦荒团队也意想到了这一点,为声明式事务供应了庞杂而丁壮夜的支持。

声明式事务治理曾是 EJB 引以为傲的一个亮点,现在 Spring 让 POJO 在事务治理方面也具有了和 EJB 一样的待遇,闪垦荒人员在 EJB 容器之外也用上了丁壮夜的声明式事务治理功用,此次要得益于 Spring 依托注入容器和 Spring AOP 的支持。依托注入容器为声明式事务治理供应了根蒂根抵举动装备,使得 Bean 对 Spring 框架而言是可治理的;而 Spring AOP 则是声明式事务治理的直接完成者,这一点经由进程清单8可以看出来。

常日情形下,笔者剧烈建议在垦荒中行使声明式事务,不只因为其庞杂,更主假定因为这样使得纯营业代码不被净化,极除夜随意后期的代码珍重。

和编程式事务比照,声明式事务独一缺少地方是,后者的最细粒度只能浸染到方法级别,没法做到像编程式事务那样可以浸染到代码块级别。然则即便有这样的需求,也存在许多变通的方法,好比,可以将需求中止事务治理的代码块自力为方法等等。

上面就来看看 Spring 为我们供应的声明式事务治理功用。

基于 TransactionInter… 的声明式事务治理

最初,Spring 供应了 TransactionInterceptor 类来实行声明式事务治理功用。先看清单8的设置配备铺排文件:

清单 8. 基于 TransactionInterceptor 的事务治理示例设置配备铺排文件
<beans...>
......
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="transfer">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="bankServiceTarget"
class="footmark.spring.core.tx.declare.origin.BankServiceImpl">
<property name="bankDao" ref="bankDao"/>
</bean>
<bean id="bankService"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="bankServiceTarget"/>
<property name="interceptorNames">
<list>
<idref bean="transactionInterceptor"/>
</list>
</property>
</bean>
......
</beans>

首先,我们设置配备铺排了一个 TransactionInterceptor 来界说相关的事务划定礼貌,他有两个次要的属性:一个是 transactionManager,用来指定一个事务治理器,并将具体事务相关的操作请托给它;其他一个是 Properties 类型的 transactionAttributes 属性,它次要用来界说事务划定礼貌,该属性的每一个键值对中,键指定的是方法名,方法名可以行使通配符,而值就泄漏表现呼应方法的所运用的事务属性。

指定事务属性的取值有较庞杂的划定礼貌,这在 Spring 中算得上是一件让人头疼的事。具体的书写划定礼貌以下:

流传举动 [,隔离级别] [,只读属性] [,超时属性] [不影响提交的异常] [,致使回滚的异常]
  • 流传举动是独一必需设置的属性,其他都可以疏忽,Spring为我们供应了合理的默许值。
  • 流传举动的取值必需以“PROPAGATION_”开首,具体包括:PROPAGATION_MANDATORY、 PROPAGATION_NESTED、PROPAGATION_NEVER、PROPAGATION_NOT_SUPPORTED、 PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_SUPPORTS,共七种取 值。
  • 隔离级其他取值必需以“ISOLATION_”开首,具体包括:ISOLATION_DEFAULT、 ISOLATION_READ_COMMITTED、ISOLATION_READ_UNCOMMITTED、 ISOLATION_REPEATABLE_READ、ISOLATION_SERIALIZABLE,共五种取值。
  • 假定事务是只读的,那末我们可以指定只读属性,行使“readOnly”指定。否则我们不需求设置该属性。
  • 超时属性的取值必需以“TIMEOUT_”开首,后面跟一个int类型的值,泄漏表现超不时辰,单元是秒。
  • 不影响提交的异常是指,即便事务中抛出了这些类型的异常,事务任然正常提交。必需在每一个异常的名字后面加上“+”。异常的名字可所以类名的一部份。好比“+RuntimeException”、“+tion”等等。
  • 致使回滚的异常是指,当事务中抛出这些类型的异常时,事务将回滚。必需在每一个异常的名字后面加上“-”。异常的名字可所以类名的悉数或部份,好比“-RuntimeException”、“-tion”等等。

以下是两个示例:

<property name="*Service">
PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,TIMEOUT_20,
+AbcException,+DefException,-HijException
</property>

以上表达式泄漏表现,针对一切方法名以 Service 收尾的方法,行使 PROPAGATION_REQUIRED 事务流传举动,事务的隔离级别是 ISOLATION_READ_COMMITTED,超不时辰为20秒,当事务抛出 AbcException 或 DefException 类型的异常,则仍然提交,当抛出 HijException 类型的异常时必需回滚事务。这里没有指定”readOnly”,泄漏表现事务不是只读的。

<property name="test">PROPAGATION_REQUIRED,readOnly</property>

以上表达式泄漏表现,针对一切方法名为 test 的方法,行使 PROPAGATION_REQUIRED 事务流传举动,而且该事务是只读的。除此之外,其他的属性均行使默许值。好比,隔离级别和超不时辰行使底层事务性成本的默许值,而且当发生发火未搜检异 常,则回滚事务,发生发火已搜检异常则仍提交事务。

设置配备铺排好了 TransactionInterceptor,我们还需求设置配备铺排一个 ProxyFactoryBean 来组装 target 和advice。这也是范例的 Spring AOP 的做法。经由进程 ProxyFactoryBean 生成的署理类就是织入了事务治理逻辑后的目的类。至此,声明式事务治理就算是完成了。我们没有对营业代码中止任何操作,一切设置均在设置配备铺排文件中完 成,这就是声明式事务的最除夜优点。

基于 TransactionProxy… 的声明式事务治理

后面的声明式事务虽然好,然则却存在一个异常恼人的成就:设置配备铺排文件太多。我们必需针对每一个目的对象设置配备铺排一个 ProxyFactoryBean;其他,虽然可以经由进程父子 Bean 的体式格式来复用 TransactionInterceptor 的设置配备铺排,然则理想的复用几率也不高;这样,加上目的对象本人,每一个营业类可以需求对应三个 <bean/> 设置配备铺排,跟着营业类的增多,设置配备铺排文件将会变得越来越重除夜,治理设置配备铺排文件又成了成就。

为了减缓这个成就,Spring 为我们供应了 TransactionProxyFactoryBean,用于将TransactionInterceptor 和 ProxyFactoryBean 的设置配备铺排合二为一。如清单9所示:

清单9. 基于 TransactionProxyFactoryBean 的事务治理示例设置配备铺排文件
<beans......>
......
<bean id="bankServiceTarget"
class="footmark.spring.core.tx.declare.classic.BankServiceImpl">
<property name="bankDao" ref="bankDao"/>
</bean>
<bean id="bankService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target" ref="bankServiceTarget"/>
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="transfer">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
......
</beans>

如斯一来,设置配备铺排文件与先前比照简化了许多。我们把这类设置配备铺排体式格式称为 Spring 经典的声明式事务治理。信任在晚期行使 Spring 的垦荒人员对这类设置配备铺排声明式事务的体式格式一定异常熟习。

然则,显式为每一个营业类设置配备铺排一个 TransactionProxyFactoryBean 的做法将使得代码显得过于机械,为此我们可以行使自动树立署理的体式格式来将其简化,行使自动树立署理是纯 AOP 常识,请读者参考相关文档,不在此赘述。

基于 <tx> 命名空间的声明式事务治理

后面两种声明式事务设置配备铺排体式格式奠基了 Spring 声明式事务治理的基石。在此根蒂根抵上,Spring 2.x 引入了 <tx> 命名空间,连络行使 <aop> 命名空间,带给垦荒人员设置配备铺排声明式事务的全新体验,设置配备铺排变得加倍庞杂和无邪。其他,得益于 <aop> 命名空间的切点表达式支持,声明式事务也变得加倍丁壮夜。

如清单10所示:

清单10. 基于 <tx> 的事务治理示例设置配备铺排文件
<beans......>
......
<bean id="bankService" 
class="footmark.spring.core.tx.declare.namespace.BankServiceImpl">
<property name="bankDao" ref="bankDao"/>
</bean>
<tx:advice id="bankAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="transfer" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>

<aop:config>
<aop:pointcut id="bankPointcut" expression="execution(* *.transfer(..))"/>
<aop:advisor advice-ref="bankAdvice" pointcut-ref="bankPointcut"/>
</aop:config>
......
</beans>

假定默许的事务属性就可以知足要求,那末代码简化为如清单 11 所示:

清单 11. 简化后的基于 <tx> 的事务治理示例设置配备铺排文件
<beans......>
......
<bean id="bankService"
class="footmark.spring.core.tx.declare.namespace.BankServiceImpl">
<property name="bankDao" ref="bankDao"/>
</bean>
<tx:advice id="bankAdvice" transaction-manager="transactionManager">
<aop:config>
<aop:pointcut id="bankPointcut" expression="execution(**.transfer(..))"/>
<aop:advisor advice-ref="bankAdvice" pointcut-ref="bankPointcut"/>
</aop:config>
......
</beans>

因为行使了切点表达式,我们就不需求针对每一个营业类树立一个署理对象了。其他,假定设置配备铺排的事务治理器 Bean 的名字取值为“transactionManager”,则我们可以省略 <tx:advice> 的 transaction-manager 属性,因为该属性的默许值即为“transactionManager”。

基于 @Transactional 的声明式事务治理

除基于命名空间的事务设置配备铺排体式格式,Spring 2.x 还引入了基于 Annotation 的体式格式,具体次要触及@Transactional 标注。@Transactional 可以浸染于接口、接口方法、类和类方法上。算作用于类上时,该类的一切 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别行使该标注来笼盖类级其他界说。如清单12所示:

清单12. 基于 @Transactional 的事务治理示例设置配备铺排文件
@Transactional(propagation = Propagation.REQUIRED)
public boolean transfer(Long fromId, Long toId, double amount) {
return bankDao.transfer(fromId, toId, amount);
}

Spring 行使 BeanPostProcessor 来处置责罚 Bean 中的标注,是以我们需求在设置配备铺排文件中作以下声明来激活该后处置责罚 Bean,如清单13所示:

清单13. 启用后处置责罚Bean的设置配备铺排
<tx:annotation-driven transaction-manager="transactionManager"/>

与后面相反,transaction-manager 属性的默许值是 transactionManager,假定事务治理器 Bean 的名字即为该值,则可以省略该属性。

虽然 @Transactional 注解可以浸染于接口、接口方法、类和类方法上,然则 Spring 小组建议不要在接口或接口方法下行使该注解,因为这只需外行使基于接口的署理时它才会生效。其他, @Transactional 注解理应只被运用到 public 方法上,这是由 Spring AOP 的实质决意的。假定你在 protected、private 或默准许见性的方法下行使 @Transactional 注解,这将被疏忽,也不会抛出任何异常。

基于 <tx> 命名空间和基于 @Transactional 的事务声明体式格式各有优瑕玷。基于 <tx> 的体式格式,其优点是与切点表达式连络,功用丁壮夜。行使切点表达式,一个设置配备铺排可以婚配多个方法,而基于 @Transactional 的体式格式必需在每一个需求行使事务的方法或类上用 @Transactional 标注,虽然可以除夜多半事务的划定礼貌是不合的,然则对 @Transactional 而言,也没法重用,必需一一指定。其他一方面,基于 @Transactional 的体式格式行使起来异常庞杂清晰了了,没有进修成本。垦荒人员可以凭证需求,任选个中一种行使,甚至也可以凭证需求夹杂行使这两种体式格式。

假定不是对遗留代码中止珍重,则不建议再行使基于 TransactionInterceptor 和基于TransactionProxyFactoryBean 的声明式事务治理体式格式,然则,进修这两种体式格式异常无益于对底层完成的理解。

虽然上面共枚举了四种声明式事务治理体式格式,然则这样的划分只是为了便于理解,其实后台的完成体式格式是一样的,只是用户行使的体式格式不合而已。


停止语

本教程的常识点除夜致总结以下:

  • 基于 TransactionDefinition、PlatformTransactionManager、TransactionStatus 编程式事务治理是 Spring 供应的最原始的体式格式,常日我们不会这么写,然则意见这类体式格式对理解 Spring 事务治理的实质有很鸿文用。
  • 基于 TransactionTemplate 的编程式事务治理是对上一种体式格式的封装,使得编码更庞杂、了了。
  • 基于 TransactionInterceptor 的声明式事务是 Spring 声明式事务的根蒂根抵,常日也不建议行使这类体式格式,然则与后面一样,意见这类体式格式对理解 Spring 声明式事务有很鸿文用。
  • 基于 TransactionProxyFactoryBean 的声明式事务是上中体式格式的改良版本,简化的设置配备铺排文件的书写,这是 Spring 晚期举荐的声明式事务治理体式格式,然则在 Spring 2.0 中已不举荐了。
  • 基于 <tx> 和 <aop> 命名空间的声明式事务治理是今朝举荐的体式格式,其最除夜特色是与 Spring AOP 连络慎密,可以富余行使切点表达式的丁壮夜支持,使得治理事务加倍无邪。
  • 基于 @Transactional 的体式格式将声明式事务治理简化到了极致。垦荒人员只需在设置配备铺排文件中加上一行启用相关后处置责罚 Bean 的设置配备铺排,然后在需求实行事务治理的方法或类下行使 @Transactional 指定事务划定礼貌即可完成事务治理,而且功用也没需求其他体式格式减色。
全面分析_Spring_的编程式事务管理及声明式事务管理. 立即下载

相关推荐

使用amp训练出现Detected call of lr_scheduler.step() before optimizer.step().

这个警告是怎么产生的?是由于在算梯度的时候出现了nan,所以这一次更新会跳过,但是参数仍旧会更新所以出现了问题,按下面的做法加一个判断就行了。但是在使用amp进行混合精度训练出现的一个warning,调换代码顺序也不work。正常在训练的时候,对于优化器和参数更新的顺序这样就可以了。

weixin_46214675的博客 1306

Spring进行编程式事务管理和声明式事务管理

Spring事务管理 PlatformTransaction接口 void commit(TransactionStatusstatus) Commit the given transaction, with regard to its status. TransactionStatus getTransaction(Transacti...

jiuweideqixu的博客 278

技术解析:ChangeFormer——基于Transformer的孪生网络在遥感变化检测中的创新应用

本文深入解析了ChangeFormer模型在遥感变化检测中的创新应用,该模型基于Transformer架构和孪生网络(Siamese Network),显著提升了变化检测的精度和效率。通过详细的技术实现和实战经验分享,展示了其在建筑物变化、森林监测等场景中的卓越表现,为相关领域的研究和应用提供了有力工具。

weixin_29102619的博客 496

Spring中的编程式、声明式事务

事务(Transaction)是数据库管理系统中的一个重要概念,它是一个原子性的数据库操作序列。在Spring框架中,事务管理是一个核心功能,它允许开发者以声明式或编程式的方式来处理事务,从而确保数据库操作的ACID特性。事务的隔离级别决定了事务操作的可见性和其他事务的干扰程度。这意味着,事务内的操作是不可分割的。:这是一个对象,代表了当前事务的状态,它可以被用来查询事务的当前状态,或者控制事务的执行(如设置回滚标志)。

weixin_44929475的博客 1339

在Ubuntu 18下安装SIMULIA Abaqus 2020

参考资料: https://github.com/imirzov/Install-Abaqus-2019-on-Ubuntu-18.04-LTS 安装环境: Ubuntu 18.4 LTS 软件版本: SIMULIA for Linux 2020 1 准备 安装光盘及破解文件 解压光盘至一目录,不能挂载,因为要修改文件内容 /home/sunwk/Downloads/abaqus2020 更改文件权限为最大 sudo chmod -R 777 abaqus2020/ * 复制libpng12

oak619的博客 1万+

2023年5月青少年软件编程Python等级考试四级真题(含答案和解析)

电子学会,2023年5月,青少年软件编程,Python等级考试,四级真题(含答案和解析)

m0_37554648的博客 904

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

摘要 Spring 的事务管理是 Spring 框架中一个比较重要的知识点,该知识点本身并不复杂,只是由于其比较灵活,导致初学者很难把握。本教程从基础知识开始,详细分析了 Spring 事务管理的使用方法,为读者理清思路。 先决条件 本教程假定您已经掌握了 Java 基础知识,并对 Spring 有一定了解。您还需要具备基本的事务管理的知识,比如:事务的定义,隔离级别的概念,等等。...

aoluan2964的博客 510

SAP SEGW 事物码里的 Association 建模方式

Association 模型用于描述 OData 模型里不同 Entity Type 之间的关联关系。我们来看一个具体的例子:Principal Entity(主体):代表 association 的主导端。Cardinality(基数):指定主体实体类型和依赖实体类型之间的关系。按 F4 或点击从列表中选择。关联的多重性如下:为引用约束()指定以下参数,目的是将主体实体类型的每个键,关联到从属实体类型的一个属性:Referential Constraints 的一个例子如下: 引用约束(Referenti

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 909

spring揭秘20-spring事务02-编程式事务与声明式事务管理

本文总结自《spring揭秘》,作者王福强,非常棒的一本书,墙裂推荐;事务管理有2种实现方式,包括编程式事务管理, 声明式事务管理;1)spring的编程式事务管理有2种方式:【BusiPlatformTransactionManager】 【代码解说】1)使用PlatformTransactionManager管理事务太过底层;可以借助模版方法模式与回调接口对PlatformTransactionManager事务管理逻辑进行封装,即使用TransactionTemplate进行编程式事务管理;1)Tra

PacosonSWJTU的博客 1649

在 SAP BTP 中玩转工厂日历 Maintain Factory Calendars 实战指南

工厂日历是企业关键的时间主数据,基于国家假日历定义工作日与非工作日,广泛应用于生产计划、采购交期、财务结账等业务场景。SAP系统通过三类应用(维护节假日、假日历和工厂日历)实现分层配置。工厂日历作为顶层配置,支持工作日模式设定和例外规则添加。在多系统架构中,工厂日历可通过集成场景同步,确保数据一致性。应用支持创建、编辑和查看功能,包含有效期设置、例外规则管理和多语言文本维护。合理设置工厂日历对业务运营至关重要,需注意命名规范和有效期选择,避免历史数据问题。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 222

YOLOv8 交通违规检测各个场景的实际应用

本文介绍了基于YOLOv8的交通违规检测系统在不同场景下的应用实现。系统可检测闯红灯、超速、违停和不系安全带等多种违规行为,针对每种场景提供了具体的技术方案和Python实现代码。其中闯红灯检测结合信号灯状态分析,超速检测通过距离时间计算速度,违停检测采用长时间跟踪策略,安全带检测则需更高精度识别。文章还展示了如何整合各功能构建综合交通监管系统,并总结了不同应用场景的技术要点和优化方向,为智能交通管理提供了实用解决方案。

u010117029的博客 299

Spring事务-两种开启事务管理的方式:基于注解的声明式事务管理、基于编程式的事务管理

基于注解的声明式事务管理 这种方式使用注解来定义事务,通过在需要进行事务管理的方法上添加相应的注解来标识事务的边界和属性。 基于编程式的事务管理 编程式事务管理是一种通过编程方式手动控制事务的管理过程。与声明式事务管理相比,它不依赖于特定的注解或配置,而是在代码中显式地编写事务管理逻辑。在编程式事务管理中,开发人员需要手动管理事务的开始、提交、回滚等过程。

小孔靠得住的博客 2210

CloudCompare&PCL 体元累加法(树冠体积计算)

文章目录

dayuhaitang1的博客 1552

Spring事务管理:从编程式到声明式的进阶之路

关注点分离:事务管理与业务逻辑解耦配置集中化:统一管理事务属性维护简便性:修改事务策略不影响业务代码错误处理自动化:自动回滚异常事务声明式编程:通过元数据表达意图。

m0_75107803的博客 834

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Spring事务管理-编程式事务、声明式事务

事务管理是应用系统中必不可少的一部分,它保证了用户的每一次操作都是可靠的,即便是出现了异常情况,也不至于破坏后台数据的完整性。   Spring提供了丰富的事务管理功能,Spring的事务管理分为编程式事务管理和声明式事务管理两种方式。编程式事务管理指通过编码的方式实现事务管理,声明式事务基于AOP,将业务逻辑与事务处理解耦。声明式事务对代码侵入较少,在实际使用中使用比较广泛。一、包依赖;二、编程式事务;三、声明式

xktxoo的博客 5741

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

声明式 vs 编程式:Spring事务管理全对比

在 Spring 框架中,声明式事务和编程式事务是实现事务管理的两种核心方式,它们在实现思路、使用场景和优缺点上有显著区别。下面从多个维度详细对比两者的差异: 2. 编程式事务 定义:在业务代码中显式编写事务管理逻辑,通过代码手动控制事务的开启、提交、回滚。 实现方式: 直接调用事务管理器(如)的 API,手动管理事务生命周期。 例如: 二、核心区别对比 维度 声明式事务 编程式事务 代码侵入性 无侵入:事务

Landcc的博客 1072

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Spring事务管理实现方式之编程式事务与声明式事务详解

1.编程式事务:编码方式实现事务管理(代码演示为JDBC事务管理) Spring实现编程式事务,依赖于2大类,分别是上篇文章提到的PlatformTransactionManager,与模版类TransactionTemplate(推荐使用)。下面分别详细介绍Spring是如何通过该类实现事务管 2.声明式事务:可知编程式事务每次实现都要单独实现,但业务量大功能复杂时,使用编程式事务无疑是痛苦的,而声明式事务不同,声明式事务属于无侵入式,不会影响业务逻辑的实现。

半山闲人的专栏 5万+

全面分析 Spring 的编程式事务管理及声明式事务管理 (超详细)

小结: 编程式事务管理:       1 基于底层API(platFormTransactionManager, TransactionStauts,,TransactionDefinition) 的编程式事务管理   2. 基于TransactionTemplate的编程式事务管理(对比基于底层API的编程式对于事务的管理启动,提交,会滚放到template中)  声明式事务管理:  实

For that dream 1978

Spring---编程式事务管理和声明式事务

优点:灵活性高,可以精确控制事务边界。缺点:增加了业务代码的复杂度。

Elmer的博客 928

Spring事务管理:声明式事务与编程式事务的应用场景

Spring事务管理提供了声明式和编程式两种方式,各有优缺点和适用场景。声明式事务基于AOP实现,配置简单,适合大多数简单场景;编程式事务提供更精细的控制,适合复杂业务流程。选择合适的事务管理方式需考虑业务复杂性、灵活性需求和性能要求。无论选择哪种方式,都需注意事务传播行为、隔离级别等属性的正确配置,以及避免常见的事务失效问题。通过合理使用Spring事务管理,可以构建更加健壮、可靠的企业级应用。

程序媛学姐的博客 1555

Spring编程式事务管理和声明式事务管理 案例

转账案例使用了Spring事务管理,用两种方式实现:编程式事务管理和声明式事物管理。    其中,编程式事务管理是一种手动修改代码的方式,比较麻烦,在开发过程中很少使用;声明式事务管理有三种方法实现,分别是TransactionProxyFactoryBean的代理方式、基于AspectJ的xml配置方式和基于注解的声明方式,后两种在开发应用中常常出现。

此处省略三千字 3407

Spring 中的事务管理方式:声明式 vs 编程式实战解析

通过。

2501_92798394的博客 513

Spring编程式事务管理和声明式事务管理

Spring 事务属性分析 事务管理对于企业应用而言至关重要。它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性。就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作过程中机器突然出故障的情况,此时,事务就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过取款机一样,以保证用户和银行的利益都不受损失。 在 Spring 中,事务是

yy193728的博客 498

Spring实现注解(编程式事务管理、通过XML或注解的声明式事务管理)

编程式事务管理、通过XML或注解的声明式事务管理

yu的博客 663
上一篇: spring的AOP和事务
下一篇: Java数据类型
andybbc
博客等级 码龄11年 64粉丝 93原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值