- 浏览: 216181 次
- 性别:
- 来自: 北京
文章分类
Spring事物提供的好处:
1.Provides a consistent programming model across different transaction APIs such as JTA, JDBC, Hibernate, JPA, and JDO
根据不同的事物API,如JTA,JDBC,Hibernate,JPA,JDO,提供了一致的编程模式。
2.Supports declarative transaction management
支持声明式事物管理
3.Provides a simpler API for programmatic transaction management than a number of complex transaction APIs such as JTA
相比与一些负责的事物API如JTA,提供了一种简单安全事务管理API。
事物的分类:
Global Transactions(全局事务)
Global transactions have a significant downside, in that code needs to use JTA, and JTA is a cumbersome API to use (partly due to its exception model). Furthermore, a JTA UserTransaction normally needs to be sourced from JNDI: meaning that we need to use both JNDI and JTA to use JTA. Obviously all use of global transactions limits the reusability of application code, as JTA is normally only available in an application server environment. Previously, the preferred way to use global transactions was via EJB CMT (Container Managed Transaction): CMT is a form of declarative transaction management (as distinguished from programmatic transaction management). EJB CMT removes the need for transaction-related JNDI lookups - although of course the use of EJB itself necessitates the use of JNDI. It removes most of the need (although not entirely) to write Java code to control transactions. The significant downside is that CMT is tied to JTA and an application server environment. Also, it is only available if one chooses to implement business logic in EJBs, or at least behind a transactional EJB facade. The negatives around EJB in general are so great that this is not an attractive proposition, especially in the face of compelling alternatives for declarative transaction management.
全局的事物有一个严重的下滑趋势,使用全局事物的代码需要使用JTA,并且JTA是一个沉重的API,此外,JTA事物通常来源于JNDI,意味着我们要使用JTA需要同时使用JNDI和JTA。很明显,所有全局事务的使用受限于应用代码的重用性。因此JTA通常只在一个应用服务环境中可用。之前全局事务受追捧是凭借EJB的CMT。CMT是一个声明式事物管理形式。EJB CVMT移除掉了对与事物相关的JDDI字典的依赖。尽管EJB本身的使用需要使用JNDI,但是他移除掉了大部分需要写java代码控制事物。严重下滑的趋势是由于CMT和JTA和一个应用服务环境相关。所以,当有一个需求去实现EJB下的商业逻辑时使用全局事物。或者至少基于EJB事物门面。EJB的副作用比较大通常也是EJB不是一个吸引人的论点。尤其在面临声明式事物管理的选择时。
Local Transactions(本地事物)
Local transactions may be easier to use, but have significant disadvantages: they cannot work across multiple transactional resources. For example, code that manages transactions using a JDBC connection cannot run within a global JTA transaction. Another downside is that local transactions tend to be invasive to the programming model.
Spring resolves these problems. It enables application developers to use a consistent programming model in any environment. You write your code once, and it can benefit from different transaction management strategies in different environments. The Spring Framework provides both declarative and programmatic transaction management. Declarative transaction management is preferred by most users, and is recommended in most cases.
With programmatic transaction management, developers work with the Spring Framework transaction abstraction, which can run over any underlying transaction infrastructure. With the preferred declarative model, developers typically write little or no code related to transaction management, and hence don't depend on the Spring Framework's transaction API (or indeed on any other transaction API).
本地事物可以更容易使用,但是有严重的缺点。不能跨多个事物工作。例如。使用JDBC管理事物的代码不能在一个全局的JTA事物中运行。另一个缺点是本地事物是一个侵入式的编程模式。
Spring解决了这些问题。他能是应用开发者在不同环境中使用同一个编程模式。你只需要写一次代码,它就能运行于不同环境的不同事物管理策略。Spring提供了声明式事物和编程式的事物。声明式编程事物管理是大多数使用者追捧的。并且被建议大多数情况下使用。
使用编程式事物管理,开发者使用Spring抽象事物。就可以运行在任何事物结构下。使用受欢迎的声明式事物。开发者可以写一点或是不写代码完成事物管理。因此不依赖于spring事物API。
Spring抽象事物的关键就是定义了一个事物策略。就是transtraction下的PlatformTransactionManager 接口。该接口一个包含3个抽象方法。
TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
不管你是青睐于声明式事物还是编程式事物,定义正确的PlatformTransactionManager 的实现是必要的。
PlatformTransactionManager implementations normally require knowledge of the environment in which they work: JDBC, JTA, Hibernate
PlatformTransactionManager 的实现通常需要JDBC、JTA、Hibernate的工作环境。
下面定义一个JDBC数据源,然后使用DataSourceTransactionManager(PlatformTransactionManager 的一个实现类),并且给他一个指向新定义数据源的额引用。
JDBC事物实例如下:
数据源:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
事物管理器:
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
如果使用JTA事物,我们就使用容器的数据源凭借JNDI包含进来。结合JtaTransactionManager。JtaTransactionManager不需要了解数据源的信息,他将使用容器的全局事物管理结构。
实例:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
<!-- other <bean/> definitions here -->
</beans>
注意:The above definition of the 'dataSource' bean uses the <jndi-lookup/> tag from the 'jee' namespace.
以上的数据源的定义使用的jee命名空间下的jndi-lookup标签
hiberante事物
hiberante事物的实现类是HibernateTransactionManager。实例如下。
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
</value>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
注:hibernate需要引用上面定义的数据源,定义了sessionFactory,sessionFactory实际是一个缓存。可以缓存对象和查询结果(以sql为key,查询结果为value)。mappingResources包含了引入的表与实体映射文件。
hibernateProperties定义了相关的属性。如方言等。
如果使用hiberante或是其他和JTA,直接定义
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>就行。
如果使用spring管理JDBC事物,可以使用一些工具类获取connection,如
Connection conn = DataSourceUtils.getConnection(dataSource);
声明式事物管理
Most users of the Spring Framework choose declarative transaction management. It is the option with the least impact on application code, and hence is most consistent with the ideals of a non-invasive lightweight container.
大多数spring框架的使用者选择声明式事物管理。它是最少的影响应用代码的一个选项。
因此是最方便的无侵入轻量级容器的想法。
Spring的AOP使得声明式事物成为了可能。尽管面向方面的事物随着spring发布了,并且可能用于样板文件中,为了有效使用这段代码不必必须去理解aop的概念。
Spring声明式事物的好处
1.Unlike EJB CMT, which is tied to JTA, the Spring Framework's declarative transaction management works in any environment. It can work with JDBC, JDO, Hibernate or other transactions under the covers, with configuration changes only.
不像EJB的CMT,和JTA联系在一起,Spring的声明事物管理可以工作在任何环境里。在幕后他可以与JDBC,JDO,Hibernate或是其他事物工作在一起。并且只需要修改配置文件。
The Spring Framework enables declarative transaction management to be applied to any class, not merely special classes such as EJBs.
Spring框架能使声明事物管理任何类,不仅仅是像EJB的特殊类
The Spring Framework offers declarative rollback rules: this is a feature with no EJB equivalent. Both programmatic and declarative support for rollback rules is provided.
Spring框架提供声明式事物回滚规则,这是一个EJB不具有的特点。编程式事物和声明式事物都支持回滚规则
The Spring Framework gives you an opportunity to customize transactional behavior, using AOP. For example, if you want to insert custom behavior in the case of transaction rollback, you can. You can also add arbitrary advice, along with the transactional advice. With EJB CMT, you have no way to influence the container's transaction management other than setRollbackOnly().
Spring框架给你一个自定义事物行为的机会,使用AOP,例如,如果你想在事物回滚时插入自定义的行为。你也可以随着事物建议插入强制的建议。使用EJB的CMT,你没有方式去影响容器的事物管理。除了使用setRollbackOnly().
The Spring Framework does not support propagation of transaction contexts across remote calls, as do high-end application servers. If you need this feature, we recommend that you use EJB. However, consider carefully before using such a feature, because normally, one does not want transactions to span remote calls.
Spring框架不支持跨远程方法调用的事物上下文传播。作为高端服务器。如果你需要这个特点。我们建议你使用EJB。然而在使用这样一个特点之前你仔细考虑一下。因为通常情况下,不希望事物跨远程方法调用。
Spring声明式事物的实现原理
Spring声明式事物凭借的是AOP 代理,AOP代理使用的是一个TransactionInterceptor 配合PlatformTransactionManager 的实现类去驱动事物相关的方法被调用。
实例:
package x.y.service;
public interface FooService {
Foo getFoo(String fooName);
Foo getFoo(String fooName, String barName);
void insertFoo(Foo foo);
void updateFoo(Foo foo);
}
如果前两个方法要在事物的读的上下文中进行,后两个要在事物的读、写的上下文中进行。
采用下面的配置上面的问题就可以都得到解决。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!-- 这个service对象要做事物的 -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<!-- 定义发生了什么 -->
<aop:advisor/>
<tx:advice id="txAdvice" transaction-manager="txManager">//指明事物管理器
<!-- 事物语义-->
<tx:attributes>
<!-- 所有以get开头的方法是只读的-->
<tx:method name="get*" read-only="true"/>
<!-- 其他的方法采用默认的事物即读写 -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- -->
<aop:config>
<aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>//定义切点,FooService包下的任意一个方法,该方法是任意参数,任意返回任何参数类型的
<aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>//链接advice和pointcut是advisor
</aop:config>
<!--定义DBCP数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>
<property name="username" value="scott"/>
<property name="password" value="tiger"/>
</bean>
<!--使用JDBC数据源,如果使用Hibernate,则下面引用要用sessionFactory -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- other <bean/> definitions here -->
</beans>
注:The transaction semantics that we want to apply are encapsulated in the <tx:advice/> definition
我们要使用的事物语义被封装在<tx:advice/>定义中。
事物的回滚
Spring事物架构默认情况下当运行时抛出 unchecked exceptions只有标准了rollback才会进行事物的回滚。就是抛出了 一个异常实例或是RuntimeException的之类。 unchecked exceptions从事物方法中抛出将不会导致事物的回滚。
下面是一个基于xml配置的标准事物回滚的实例。
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" rollback-for="NoProductInStockException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
当然还可以指定即使出现异常仍然提交事物
实例如下:
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="updateStock" no-rollback-for="InstrumentNotFoundException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
出现任何异常都进行事物回滚的实例
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="*" rollback-for="Throwable"/>
</tx:attributes>
</tx:advice>
为不同的beans配置不同的事物语义(<aop:advisor/>)
假设你所有服务层的class都放在'x.y.service' package下,所有服务层的class以'Service' 结尾。是所有的服务都有默认的事物可以使用如下的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* x.y.service..*Service.*(..))"/>
//表示所有x.y.service包下的(包括子包)以Service结尾的任意方法
<aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/>
</aop:config>
<!-- these two beans will be transactional... -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<bean id="barService" class="x.y.service.extras.SimpleBarService"/>
<!-- ... and these two beans won't -->
<bean id="anotherService" class="org.xyz.SomeService"/> <!-- (not in the right package) -->
<bean id="barManager" class="x.y.service.SimpleBarManager"/> <!-- (doesn't end in 'Service') -->
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- other transaction infrastructure beans such as a PlatformTransactionManager omitted... -->
</beans>
也可以定义多个advice和advisor如下:
<aop:config>
<aop:pointcut id="defaultServiceOperation"
expression="execution(* x.y.service.*Service.*(..))"/>
<aop:pointcut id="noTxServiceOperation"
expression="execution(* x.y.service.ddl.DefaultDdlManager.*(..))"/>
<aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/>
<aop:advisor pointcut-ref="noTxServiceOperation" advice-ref="noTxAdvice"/>
</aop:config>
<!-- this bean will be transactional (see the 'defaultServiceOperation' pointcut) -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<!-- this bean will also be transactional, but with totally different transactional settings -->
<bean id="anotherFooService" class="x.y.service.ddl.DefaultDdlManager"/>
<tx:advice id="defaultTxAdvice">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<tx:advice id="noTxAdvice">
<tx:attributes>
<tx:method name="*" propagation="NEVER"/>
</tx:attributes>
</tx:advice>
默认的 <tx:advice/> settings
The propagation setting is REQUIRED 传播设置是必须的
The isolation level is DEFAULT 隔离级别是默认的
The transaction is read/write 事物是读写的
<tx:method/> 设置
Attribute Required? Default Description
name Yes The method name(s) with which the transaction attributes are to be associated. The wildcard (*) character can be used to associate the same transaction attribute settings with a number of methods; for example, 'get*', 'handle*', 'on*Event', and so forth.
propagation No REQUIRED The transaction propagation behavior
isolation No DEFAULT The transaction isolation level
timeout No -1 The transaction timeout value (in seconds)
read-only No false Is this transaction read-only?
rollback-for No The Exception(s) that will trigger rollback; comma-delimited. For example, 'com.foo.MyBusinessException,ServletException'
no-rollback-for No The Exception(s) that will not trigger rollback; comma-delimited. For example, 'com.foo.MyBusinessException,ServletException'
tx:method的name是必须的,如指定get*开头的。
propagation属性默认是required。
isolation 事物的隔离级别默认是default
read-only 属性也是默认是false
rollback-for 指定出现哪些异常要进行事物的回滚
下面使用@Transactional事物
这个功能必须是在java5或是之上版本才可用
实例:
@Transactional
public class DefaultFooService implements FooService {
Foo getFoo(String fooName);
Foo getFoo(String fooName, String barName);
void insertFoo(Foo foo);
void updateFoo(Foo foo);
}
当上面的pojo被Spring容器管理,只要在配置文件中添加一行就可以是上面的服务受事物的管理。配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!-- this is the service object that we want to make transactional -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager"/>
//上面的这一行就表示声明式的事物管理了
<!-- a PlatformTransactionManager is still required -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- (this dependency is defined somewhere else) -->
<property name="dataSource" ref="dataSource"/>
</bean>
//事物管理器只需要直接引入数据源即可
<!-- other <bean/> definitions here -->
</beans>
@Transactional可以被使用在接口上,接口的方法上,一个class上,或是一个class的方法上。
Spring的开发团队建议@Transactional被用到实体bean上,反对作用在接口上,如果你作用在接口上,只有你使用interface-based proxies(基于接口的代理)才会工作,如果使用class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj"),被设置的类将不会生效事物的管理。
模式使用的是代理模式,这种代理模式是对外方法进行链接的。内部的对象调用另一个对象的方法将不会被拦截。
<tx:annotation-driven/> settings
attribute default
transaction-manager transactionManager
mode proxy
proxy-target-class false
注意:<tx:annotation-driven/>只会寻找同一个应用上下文锁定义有@Transactional 的beans。
如果你把 <tx:annotation-driven/>放到DispatcherServlet对应的ApplicationContext,就只会寻找controller里面的@Transactional 的beans。而不是你的service。
在方法上设置@Transactional会优先与类上设置@Transactional
如:
@Transactional(readOnly = true)
public class DefaultFooService implements FooService {
public Foo getFoo(String fooName) {
// do something
}
// these settings have precedence for this method
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void updateFoo(Foo foo) {
// do something
}
}
上面的方法中getFoo执行类定义的事物,而updateFoo执行自己定义的事物方式。
@Transactional settings
The propagation setting is PROPAGATION_REQUIRED
The isolation level is ISOLATION_DEFAULT
The transaction is read/write
The transaction timeout defaults to the default timeout of the underlying transaction system, or or none if timeouts are not supported
Any RuntimeException will trigger rollback, and any checked Exception will not
propagation enum: Propagation optional propagation setting
isolation enum: Isolation optional isolation level
readOnly boolean read/write vs. read-only transaction
timeout int (in seconds granularity) the transaction timeout
rollbackFor an array of Class objects, which must be derived from Throwable an optional array of exception classes which must cause rollback
rollbackForClassname an array of class names. Classes must be derived from Throwable an optional array of names of exception classes that must cause rollback
noRollbackFor an array of Class objects, which must be derived from Throwable an optional array of exception classes that must not cause rollback.
noRollbackForClassname
PROPAGATION_REQUIRED表示该线程在事物的中运行
待续......
1.Provides a consistent programming model across different transaction APIs such as JTA, JDBC, Hibernate, JPA, and JDO
根据不同的事物API,如JTA,JDBC,Hibernate,JPA,JDO,提供了一致的编程模式。
2.Supports declarative transaction management
支持声明式事物管理
3.Provides a simpler API for programmatic transaction management than a number of complex transaction APIs such as JTA
相比与一些负责的事物API如JTA,提供了一种简单安全事务管理API。
事物的分类:
Global Transactions(全局事务)
Global transactions have a significant downside, in that code needs to use JTA, and JTA is a cumbersome API to use (partly due to its exception model). Furthermore, a JTA UserTransaction normally needs to be sourced from JNDI: meaning that we need to use both JNDI and JTA to use JTA. Obviously all use of global transactions limits the reusability of application code, as JTA is normally only available in an application server environment. Previously, the preferred way to use global transactions was via EJB CMT (Container Managed Transaction): CMT is a form of declarative transaction management (as distinguished from programmatic transaction management). EJB CMT removes the need for transaction-related JNDI lookups - although of course the use of EJB itself necessitates the use of JNDI. It removes most of the need (although not entirely) to write Java code to control transactions. The significant downside is that CMT is tied to JTA and an application server environment. Also, it is only available if one chooses to implement business logic in EJBs, or at least behind a transactional EJB facade. The negatives around EJB in general are so great that this is not an attractive proposition, especially in the face of compelling alternatives for declarative transaction management.
全局的事物有一个严重的下滑趋势,使用全局事物的代码需要使用JTA,并且JTA是一个沉重的API,此外,JTA事物通常来源于JNDI,意味着我们要使用JTA需要同时使用JNDI和JTA。很明显,所有全局事务的使用受限于应用代码的重用性。因此JTA通常只在一个应用服务环境中可用。之前全局事务受追捧是凭借EJB的CMT。CMT是一个声明式事物管理形式。EJB CVMT移除掉了对与事物相关的JDDI字典的依赖。尽管EJB本身的使用需要使用JNDI,但是他移除掉了大部分需要写java代码控制事物。严重下滑的趋势是由于CMT和JTA和一个应用服务环境相关。所以,当有一个需求去实现EJB下的商业逻辑时使用全局事物。或者至少基于EJB事物门面。EJB的副作用比较大通常也是EJB不是一个吸引人的论点。尤其在面临声明式事物管理的选择时。
Local Transactions(本地事物)
Local transactions may be easier to use, but have significant disadvantages: they cannot work across multiple transactional resources. For example, code that manages transactions using a JDBC connection cannot run within a global JTA transaction. Another downside is that local transactions tend to be invasive to the programming model.
Spring resolves these problems. It enables application developers to use a consistent programming model in any environment. You write your code once, and it can benefit from different transaction management strategies in different environments. The Spring Framework provides both declarative and programmatic transaction management. Declarative transaction management is preferred by most users, and is recommended in most cases.
With programmatic transaction management, developers work with the Spring Framework transaction abstraction, which can run over any underlying transaction infrastructure. With the preferred declarative model, developers typically write little or no code related to transaction management, and hence don't depend on the Spring Framework's transaction API (or indeed on any other transaction API).
本地事物可以更容易使用,但是有严重的缺点。不能跨多个事物工作。例如。使用JDBC管理事物的代码不能在一个全局的JTA事物中运行。另一个缺点是本地事物是一个侵入式的编程模式。
Spring解决了这些问题。他能是应用开发者在不同环境中使用同一个编程模式。你只需要写一次代码,它就能运行于不同环境的不同事物管理策略。Spring提供了声明式事物和编程式的事物。声明式编程事物管理是大多数使用者追捧的。并且被建议大多数情况下使用。
使用编程式事物管理,开发者使用Spring抽象事物。就可以运行在任何事物结构下。使用受欢迎的声明式事物。开发者可以写一点或是不写代码完成事物管理。因此不依赖于spring事物API。
Spring抽象事物的关键就是定义了一个事物策略。就是transtraction下的PlatformTransactionManager 接口。该接口一个包含3个抽象方法。
TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
不管你是青睐于声明式事物还是编程式事物,定义正确的PlatformTransactionManager 的实现是必要的。
PlatformTransactionManager implementations normally require knowledge of the environment in which they work: JDBC, JTA, Hibernate
PlatformTransactionManager 的实现通常需要JDBC、JTA、Hibernate的工作环境。
下面定义一个JDBC数据源,然后使用DataSourceTransactionManager(PlatformTransactionManager 的一个实现类),并且给他一个指向新定义数据源的额引用。
JDBC事物实例如下:
数据源:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
事物管理器:
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
如果使用JTA事物,我们就使用容器的数据源凭借JNDI包含进来。结合JtaTransactionManager。JtaTransactionManager不需要了解数据源的信息,他将使用容器的全局事物管理结构。
实例:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
<!-- other <bean/> definitions here -->
</beans>
注意:The above definition of the 'dataSource' bean uses the <jndi-lookup/> tag from the 'jee' namespace.
以上的数据源的定义使用的jee命名空间下的jndi-lookup标签
hiberante事物
hiberante事物的实现类是HibernateTransactionManager。实例如下。
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
</value>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
注:hibernate需要引用上面定义的数据源,定义了sessionFactory,sessionFactory实际是一个缓存。可以缓存对象和查询结果(以sql为key,查询结果为value)。mappingResources包含了引入的表与实体映射文件。
hibernateProperties定义了相关的属性。如方言等。
如果使用hiberante或是其他和JTA,直接定义
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>就行。
如果使用spring管理JDBC事物,可以使用一些工具类获取connection,如
Connection conn = DataSourceUtils.getConnection(dataSource);
声明式事物管理
Most users of the Spring Framework choose declarative transaction management. It is the option with the least impact on application code, and hence is most consistent with the ideals of a non-invasive lightweight container.
大多数spring框架的使用者选择声明式事物管理。它是最少的影响应用代码的一个选项。
因此是最方便的无侵入轻量级容器的想法。
Spring的AOP使得声明式事物成为了可能。尽管面向方面的事物随着spring发布了,并且可能用于样板文件中,为了有效使用这段代码不必必须去理解aop的概念。
Spring声明式事物的好处
1.Unlike EJB CMT, which is tied to JTA, the Spring Framework's declarative transaction management works in any environment. It can work with JDBC, JDO, Hibernate or other transactions under the covers, with configuration changes only.
不像EJB的CMT,和JTA联系在一起,Spring的声明事物管理可以工作在任何环境里。在幕后他可以与JDBC,JDO,Hibernate或是其他事物工作在一起。并且只需要修改配置文件。
The Spring Framework enables declarative transaction management to be applied to any class, not merely special classes such as EJBs.
Spring框架能使声明事物管理任何类,不仅仅是像EJB的特殊类
The Spring Framework offers declarative rollback rules: this is a feature with no EJB equivalent. Both programmatic and declarative support for rollback rules is provided.
Spring框架提供声明式事物回滚规则,这是一个EJB不具有的特点。编程式事物和声明式事物都支持回滚规则
The Spring Framework gives you an opportunity to customize transactional behavior, using AOP. For example, if you want to insert custom behavior in the case of transaction rollback, you can. You can also add arbitrary advice, along with the transactional advice. With EJB CMT, you have no way to influence the container's transaction management other than setRollbackOnly().
Spring框架给你一个自定义事物行为的机会,使用AOP,例如,如果你想在事物回滚时插入自定义的行为。你也可以随着事物建议插入强制的建议。使用EJB的CMT,你没有方式去影响容器的事物管理。除了使用setRollbackOnly().
The Spring Framework does not support propagation of transaction contexts across remote calls, as do high-end application servers. If you need this feature, we recommend that you use EJB. However, consider carefully before using such a feature, because normally, one does not want transactions to span remote calls.
Spring框架不支持跨远程方法调用的事物上下文传播。作为高端服务器。如果你需要这个特点。我们建议你使用EJB。然而在使用这样一个特点之前你仔细考虑一下。因为通常情况下,不希望事物跨远程方法调用。
Spring声明式事物的实现原理
Spring声明式事物凭借的是AOP 代理,AOP代理使用的是一个TransactionInterceptor 配合PlatformTransactionManager 的实现类去驱动事物相关的方法被调用。
实例:
package x.y.service;
public interface FooService {
Foo getFoo(String fooName);
Foo getFoo(String fooName, String barName);
void insertFoo(Foo foo);
void updateFoo(Foo foo);
}
如果前两个方法要在事物的读的上下文中进行,后两个要在事物的读、写的上下文中进行。
采用下面的配置上面的问题就可以都得到解决。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!-- 这个service对象要做事物的 -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<!-- 定义发生了什么 -->
<aop:advisor/>
<tx:advice id="txAdvice" transaction-manager="txManager">//指明事物管理器
<!-- 事物语义-->
<tx:attributes>
<!-- 所有以get开头的方法是只读的-->
<tx:method name="get*" read-only="true"/>
<!-- 其他的方法采用默认的事物即读写 -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- -->
<aop:config>
<aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>//定义切点,FooService包下的任意一个方法,该方法是任意参数,任意返回任何参数类型的
<aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>//链接advice和pointcut是advisor
</aop:config>
<!--定义DBCP数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>
<property name="username" value="scott"/>
<property name="password" value="tiger"/>
</bean>
<!--使用JDBC数据源,如果使用Hibernate,则下面引用要用sessionFactory -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- other <bean/> definitions here -->
</beans>
注:The transaction semantics that we want to apply are encapsulated in the <tx:advice/> definition
我们要使用的事物语义被封装在<tx:advice/>定义中。
事物的回滚
Spring事物架构默认情况下当运行时抛出 unchecked exceptions只有标准了rollback才会进行事物的回滚。就是抛出了 一个异常实例或是RuntimeException的之类。 unchecked exceptions从事物方法中抛出将不会导致事物的回滚。
下面是一个基于xml配置的标准事物回滚的实例。
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" rollback-for="NoProductInStockException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
当然还可以指定即使出现异常仍然提交事物
实例如下:
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="updateStock" no-rollback-for="InstrumentNotFoundException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
出现任何异常都进行事物回滚的实例
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="*" rollback-for="Throwable"/>
</tx:attributes>
</tx:advice>
为不同的beans配置不同的事物语义(<aop:advisor/>)
假设你所有服务层的class都放在'x.y.service' package下,所有服务层的class以'Service' 结尾。是所有的服务都有默认的事物可以使用如下的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* x.y.service..*Service.*(..))"/>
//表示所有x.y.service包下的(包括子包)以Service结尾的任意方法
<aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/>
</aop:config>
<!-- these two beans will be transactional... -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<bean id="barService" class="x.y.service.extras.SimpleBarService"/>
<!-- ... and these two beans won't -->
<bean id="anotherService" class="org.xyz.SomeService"/> <!-- (not in the right package) -->
<bean id="barManager" class="x.y.service.SimpleBarManager"/> <!-- (doesn't end in 'Service') -->
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- other transaction infrastructure beans such as a PlatformTransactionManager omitted... -->
</beans>
也可以定义多个advice和advisor如下:
<aop:config>
<aop:pointcut id="defaultServiceOperation"
expression="execution(* x.y.service.*Service.*(..))"/>
<aop:pointcut id="noTxServiceOperation"
expression="execution(* x.y.service.ddl.DefaultDdlManager.*(..))"/>
<aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/>
<aop:advisor pointcut-ref="noTxServiceOperation" advice-ref="noTxAdvice"/>
</aop:config>
<!-- this bean will be transactional (see the 'defaultServiceOperation' pointcut) -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<!-- this bean will also be transactional, but with totally different transactional settings -->
<bean id="anotherFooService" class="x.y.service.ddl.DefaultDdlManager"/>
<tx:advice id="defaultTxAdvice">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<tx:advice id="noTxAdvice">
<tx:attributes>
<tx:method name="*" propagation="NEVER"/>
</tx:attributes>
</tx:advice>
默认的 <tx:advice/> settings
The propagation setting is REQUIRED 传播设置是必须的
The isolation level is DEFAULT 隔离级别是默认的
The transaction is read/write 事物是读写的
<tx:method/> 设置
Attribute Required? Default Description
name Yes The method name(s) with which the transaction attributes are to be associated. The wildcard (*) character can be used to associate the same transaction attribute settings with a number of methods; for example, 'get*', 'handle*', 'on*Event', and so forth.
propagation No REQUIRED The transaction propagation behavior
isolation No DEFAULT The transaction isolation level
timeout No -1 The transaction timeout value (in seconds)
read-only No false Is this transaction read-only?
rollback-for No The Exception(s) that will trigger rollback; comma-delimited. For example, 'com.foo.MyBusinessException,ServletException'
no-rollback-for No The Exception(s) that will not trigger rollback; comma-delimited. For example, 'com.foo.MyBusinessException,ServletException'
tx:method的name是必须的,如指定get*开头的。
propagation属性默认是required。
isolation 事物的隔离级别默认是default
read-only 属性也是默认是false
rollback-for 指定出现哪些异常要进行事物的回滚
下面使用@Transactional事物
这个功能必须是在java5或是之上版本才可用
实例:
@Transactional
public class DefaultFooService implements FooService {
Foo getFoo(String fooName);
Foo getFoo(String fooName, String barName);
void insertFoo(Foo foo);
void updateFoo(Foo foo);
}
当上面的pojo被Spring容器管理,只要在配置文件中添加一行就可以是上面的服务受事物的管理。配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!-- this is the service object that we want to make transactional -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager"/>
//上面的这一行就表示声明式的事物管理了
<!-- a PlatformTransactionManager is still required -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- (this dependency is defined somewhere else) -->
<property name="dataSource" ref="dataSource"/>
</bean>
//事物管理器只需要直接引入数据源即可
<!-- other <bean/> definitions here -->
</beans>
@Transactional可以被使用在接口上,接口的方法上,一个class上,或是一个class的方法上。
Spring的开发团队建议@Transactional被用到实体bean上,反对作用在接口上,如果你作用在接口上,只有你使用interface-based proxies(基于接口的代理)才会工作,如果使用class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj"),被设置的类将不会生效事物的管理。
模式使用的是代理模式,这种代理模式是对外方法进行链接的。内部的对象调用另一个对象的方法将不会被拦截。
<tx:annotation-driven/> settings
attribute default
transaction-manager transactionManager
mode proxy
proxy-target-class false
注意:<tx:annotation-driven/>只会寻找同一个应用上下文锁定义有@Transactional 的beans。
如果你把 <tx:annotation-driven/>放到DispatcherServlet对应的ApplicationContext,就只会寻找controller里面的@Transactional 的beans。而不是你的service。
在方法上设置@Transactional会优先与类上设置@Transactional
如:
@Transactional(readOnly = true)
public class DefaultFooService implements FooService {
public Foo getFoo(String fooName) {
// do something
}
// these settings have precedence for this method
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void updateFoo(Foo foo) {
// do something
}
}
上面的方法中getFoo执行类定义的事物,而updateFoo执行自己定义的事物方式。
@Transactional settings
The propagation setting is PROPAGATION_REQUIRED
The isolation level is ISOLATION_DEFAULT
The transaction is read/write
The transaction timeout defaults to the default timeout of the underlying transaction system, or or none if timeouts are not supported
Any RuntimeException will trigger rollback, and any checked Exception will not
propagation enum: Propagation optional propagation setting
isolation enum: Isolation optional isolation level
readOnly boolean read/write vs. read-only transaction
timeout int (in seconds granularity) the transaction timeout
rollbackFor an array of Class objects, which must be derived from Throwable an optional array of exception classes which must cause rollback
rollbackForClassname an array of class names. Classes must be derived from Throwable an optional array of names of exception classes that must cause rollback
noRollbackFor an array of Class objects, which must be derived from Throwable an optional array of exception classes that must not cause rollback.
noRollbackForClassname
PROPAGATION_REQUIRED表示该线程在事物的中运行
待续......
发表评论
-
spring事物注意事项
2012-02-27 17:57 1765------------------------------- ... -
利用spring实现Hession
2012-02-02 14:46 2926hession是一种轻量级的远程服务,hession是借助二进 ... -
利用spring实现RMI
2012-02-01 17:09 1234RMI是实现将服务暴露给 ... -
spring之定时调度
2012-01-30 18:20 1157在java2中完成定时调度是基于Timer(启动定时器)和Ti ... -
Spring集成hibernate
2011-12-23 18:12 890方式一:使用hibernate.cfg ... -
实现简单spring的IOC
2011-12-14 08:48 964Spring的IOC让被调用者从调用者中实例化解脱出来。而是通 ... -
Spring AOP
2011-11-30 14:09 1778b]Introduction[/b] AOP(面向且面的编程) ... -
Spring 杂文
2011-11-29 10:51 8771.配置文件转换成对应的注解形式 <bean id=&q ... -
Spring注解
2011-11-28 10:21 1522注解是一种元数据(描述数据的数据),本身并不具备任何功能,sp ... -
spring时间表达式
2011-11-10 10:27 1166Cron 表达式包括以下 7 个字段: 秒 ...
相关推荐
Spring事务管理的目的是确保数据的一致性和完整性,尤其是在多操作、多资源的环境中。本Demo将深入探讨Spring如何实现事务的管理。 首先,Spring提供了两种主要的事务管理方式:编程式事务管理和声明式事务管理。 ...
### Spring事务与数据库操作 #### 一、Spring的声明式事务管理 在现代软件开发中,事务处理是非常关键的一部分,特别是在涉及多个数据操作时。Spring框架提供了强大的事务管理能力,可以方便地集成到应用程序中。...
Spring事务管理是Spring框架的核心特性之一,主要用于处理应用程序中的数据一致性问题。在Spring中,事务管理分为编程式和声明式两种方式。本篇文章将详细解释Spring事务管理的流程,以及如何通过时序图来理解这一...
本资源包提供了进行Spring事务管理开发所需的所有关键库,包括框架基础、核心组件、AOP(面向切面编程)支持、日志处理、编译工具以及与数据库交互的相关jar包。下面将对这些知识点进行详细解释: 1. **Spring框架*...
Spring事务原理和配置 Spring事务原理是指Spring框架中的一种机制,用于管理事务,并提供了多种配置方式。事务是指一系列的操作,作为一个整体执行,如果其中某个操作失败,整个事务将回滚。Spring事务原理围绕着两...
本主题将深入探讨“Spring事务案例分析.zip”中的关键知识点,包括Spring事务管理及其在实际项目中的应用。 首先,我们来了解什么是Spring事务管理。在分布式系统或数据库操作中,事务管理是确保数据一致性和完整性...
标题“Spring事务管理失效原因汇总”指出了本文的核心内容是分析在使用Spring框架进行事务管理时可能遇到的问题及其原因。描述部分进一步说明了事务失效的后果往往不明显,容易在测试环节被忽略,但在生产环境中出现...
在Spring框架中,事务管理是核心特性之一,它允许开发者以声明式或编程式的方式处理事务。本示例“spring 事务传播 demo”将聚焦于Spring的事务传播行为,这是在多个方法调用中控制事务边界的关键概念。下面我们将...
这个名为"Spring事务小demo"的项目提供了一个实践示例,帮助开发者了解Spring事务处理的基本概念和用法。 首先,Spring事务管理是Spring框架的核心特性之一,它允许我们以声明式或编程式的方式管理事务。声明式事务...
本篇将深入探讨Spring事务管理的核心概念、工作原理以及如何使用`spring-tx-3.2.0.RELEASE.jar`这个jar包。 首先,我们需要理解什么是事务。在数据库系统中,事务是一组操作,这些操作被视为一个整体,要么全部完成...
本文将深入探讨在Spring框架中如何管理事务,以“Spring 事务简单完整例子”为出发点,结合标签“spring,事务,jdbc事务”,我们将详细解释Spring事务管理的原理和实践。 首先,Spring提供了两种事务管理方式:编程...
Spring事务详细讲解 在 Spring 框架中,事务管理扮演着非常重要的角色。Spring 声明式事务让我们从复杂的事务处理中得到解脱,使得我们再也无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。再也无需要...
Spring事务机制是Java开发中非常重要的一个概念,它在企业级应用中扮演着核心角色,确保数据的一致性和完整性。Spring提供了多种事务管理方式,包括编程式事务管理和声明式事务管理。在这篇DEMO中,我们将重点探讨...
本DEMO主要探讨的是Spring事务的传播行为和隔离级别,这些概念对于理解和优化数据库操作至关重要。让我们深入理解这些概念及其实际应用。 首先,我们来谈谈事务的传播行为。在Spring中,当一个方法被另一个具有事务...
当我们在使用 Spring 所提供的事务功能时,如果是仅仅处理单个的事务,是比较容易把握事务的提交与回滚,不过一旦引入嵌套事务后,多个事务的回滚和提交就会变得复杂起来,各个事务之间是如何相互影响的,是一个值得...
Spring事务操作示例(四种方式),包含完整代码和数据库文件(基于MySQL,在项目sql文件夹中),可运行,学习Spring事务详见博客:http://blog.csdn.net/daijin888888/article/details/51822257
本篇将基于"Spring事务传播Demo"来深入探讨Spring事务管理和传播行为。 首先,我们需要理解什么是事务。在数据库操作中,事务是一组操作,这些操作要么全部执行,要么全部不执行,以确保数据的一致性和完整性。在...
Spring事务管理是Spring框架的核心特性之一,主要用于处理应用程序中的数据一致性问题。在多线程、分布式系统中,事务管理显得尤为重要。本节将详细介绍Spring如何通过XML配置和注解方式来实现事务管理。 首先,...