spring提供声明式事务管理,这是通过aop实现的,这是最少影响应用代码的选择。
通常通过
TransactionProxyFactoryBean实现事务代理。需要一个目标对象包装在事务代理中。当我们定义
TransactionProxyFactoryBean是,我们需要一个关于PlatformTransactionManager的实现引用和事务属性,是无属性含有事务定义。
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="dataSource" />
</property>
</bean>
以上代码是关于PlatformTransactionManager的实现类的定义。在事务代理定义中将引用这个javabean。
<bean id="baseTransactionProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
此处是定义事务代理,其中应用了关于PlatformTransactionManager的实现和事务属性。
spring中的事务策略
spring事务抽象的关键是事务策略的概念。这个概念由 org.springframework.transaction.PlatformTransactionManager 接口体现。
public interface PlatformTransactionManager
{
public abstract TransactionStatus getTransaction(TransactionDefinition transactiondefinition)
throws TransactionException;
public abstract void commit(TransactionStatus transactionstatus)
throws TransactionException;
public abstract void rollback(TransactionStatus transactionstatus)
throws TransactionException;
}
getTransaction根据一个类型为TransactionDefinition 参数返回一个TransactionStatus 类型的对象,返回的 TransactionStatus对象可能代表一个新的或已经存在的事 务(如果在当前调用堆栈有一个符合条件的事务)。
TransactionDefinition接口指定:
-
事务隔离:当前事务和其它事务的隔离的程度。 例如,这个事务能否看到其他事务未提交的写数据?
-
事务传播:通常在一个事务中执行的 所有代码都会在这个事务中运行。但是,如果一个事务上下文已经存在, 有几个选项可以指定一个事务性方法的执行行为:例如,简单地在现有的 事务中运行(大多数情况);或者挂起现有事务,创建一个新的事务。 Spring提供EJB CMT中熟悉的事务传播选项。
-
事务超时: 事务在超时前能运行多 久(自动被底层的事务基础设施回滚)。
-
只读状态: 只读事务不修改任何数 据。只读事务在某些情况下(例如当使用Hibernate时)可可是一种非常有用的优化
PlatformTransactionManager实现是如何定义的,它将和JDBC一起工作
首先需要定义jdbc数据源。然后使用DataSourceTransactionManager,为它提供一个数据源引用。
<bean id="dataSource" <!-- BasicDataSource的别名 -->
class="org.apache.commons.dbcp.BasicDataSource" <!-- BasicDataSource类的别名所对应的类 -->
destroy-method="close">
<property name="driverClassName"><!-- 对应BasicDataSource类中的属性 -->
<value>${jdbc.driverClassName}</value><!-- 该属性值将绑定到BasicDataSource上所对应的属性上(driverClassName) -->
</property>
<property name="url"><value>${jdbc.url}</value></property>
<property name="username"><value>${jdbc.username}</value></property>
<property name="password"><value>${jdbc.password}</value></property>
</bean>
PlatformTransactionManager的定义如下.
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="dataSource" />
</property>
</bean>
如果我们使用JTA, 我们需要使用通过JNDI获得的容器数据源,和一个JtaTransactionManager实 现。JtaTransactionManager不需要知道数据源,或任何其他特定资源,因为它将 使用容器的全局事务管理。
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>jdbc/jpetstore</value></property>
</bean>
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"/>
使用hibernate局部事务的配置
在这种情况下,我们需要定义一个Hibernate的LocalSessionFactory,应用程 序将使用它获得Hibernate的会话。
数据源bean定义和上面例子类似,这里不再罗列(如果这是容器数据源,它应该是非事务的,因为Spring会管理事务, 而不是容器)。
这种情况下,“transactionManager” bean的类型是HibernateTransactionManager。
和DataSourceTransactionManager拥有一个数据源的引用一样, HibernateTransactionManager需要一个SessionFactory的引用。
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="mappingResources">
<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>