chapter05 Spring对事务的支持
一.Spring对事物支持所采用的策略
1.spring统一各种事物的编程方式
AOP事务的含义:
事务当作一个切面,动态地织入到目标对象,形成一个代理对象。
二、Spring的事务机制
Spring支持声明式事务。
Spring使用事务服务代理和事务管理器(如HibernateTransactionManager)来支持事务服务。
Spring对事务的边界多了一种嵌套事务(PROPAGATION_NESTED)。
PROPAGATION_NESTED:
如果客户端启动了事务T1,那么Bean启动一个嵌套在T1中的子事务T2;
如果客户端没有启动事务,那么Bean会启动一个新的事务,类似于REQUIRED_NEW
1)事物的特性:
@1,传播行为:调用者如何去影响被调用者的事物
@2,隔离性
@3, 只读事物
@4,超时操作
@5,回滚规则:spring容器对bean所抛出的异常是否回滚事物
三、Spring中事务的使用
1、Spring中使用Hibernate事务
采用配置文件的方(底层用的是用AOP的方式实现的)
Step1:配置数据源
Step2:配置sessionfactory (同上)
Step3:配置事务管理器HibernateTransactionManager
<bean id="myTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="mySessionFactory" />
</property>
</bean>
Step4:配置DAO
Step5:配置目标对象
Step6:配置事务代理,为相关对象注入切面,需要将目标对象,事务管理其和传播行为传进来,客户端再调用service层对象来做事情是使用的不再是原来的service,而是这个配置了事物的代理对象
实现以上步骤的实例:
<!-- 配置数据源 spring内置-->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/tarena</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>1234</value>
</property>
</bean>
<!-- 配置SessionFactory -->
<bean id="mySessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="mappingResources">
<list>
<value>entity\Account.hbm.xml</value>
<value>entity\StockAccount.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
</props>
</property>
</bean>
<!-- 配置事务管理器 -->
<bean id="myTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="mySessionFactory" />
</property>
</bean>
<!-- 配置Dao -->
<bean id="abstractDAO" abstract="true">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
<bean id="accountDAO" class="dao.hibernate.AccountDAOHibernateImpl"
parent="abstractDAO" />
<bean id="stockDAO" class="dao.hibernate.StockDAOHibernateImpl"
parent="abstractDAO" />
<!-- 配置Service -->
<bean id="stockServiceTarget"
class="service.spring.StockServiceSpringImpl">
<property name="accountDAO" ref="accountDAO" />
<property name="stockDAO" ref="stockDAO" />
</bean>
<!-- 配置抽象的事务代理,用于继承,这样多个目标对象就可以公用一个事物管理器-->
如果不配置为抽象的。则需要在事物管理器中配置一个目标对象
<bean id="abstractService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
1)配置事务管理器
<property name="transactionManager">
<ref bean="myTransactionManager" />
</property>
2)配置事物特性
<property name="transactionAttributes">
<props>
<prop key="open*">PROPAGATION_REQUIRED,readOnly</prop>
前面一个特性配置的是事物的传播行为,必须的
后面配置的是事物的隔离特性。不是必须的。一般不常用
<!—key配置应用事物的方法,如果是*代表所有方法都应用事物-->
<prop key="open*">PROPAGATION_REQUIRED</prop>
<prop key="buyStock">PROPAGATION_REQUIRED,-StockException</prop>
+异常类型代表提交事物,-异常类型代表回滚事物
Hirbernate对运行时异常才会回滚事物,而对检测异常会提交事物,所以在设置异常处理规则时要注意该异常是否需要回滚事物
</props>
</property>
</bean>
<!—配置使用了事物管理器的目标对象,继承上面的事务管理器- - >
<bean id="stockService" parent="abstractService">
3)配置目标对象
<property name="target">
<ref bean="stockServiceTarget" />
</property>
</bean>
事务属性描述格式:
传播行为,隔离级别,只读事务(read-only),回滚规则
在默认情况下,Spring的容器对于非受查异常(服务模块中抛出的非受查异常),会回滚事务。对于受查异常,会提交事务。
如果即种受查异常,也要回滚事务,可以用 “- 异常类型“来声明。同样,对于非受查异常,如果不要求回滚事务,可以用"+异常类型"来声明。
如何简化事务配置?
采用标注的方式(jdk要求是1.5以上的) 让spring管理hirbernate事物
1.首先引入命名空间
<?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.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<!-- 配置数据源 spring内置-->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/test</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>root</value>
</property>
</bean>
<!-- 配置SessionFactory -->
<bean id="mySessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="mappingResources">
<list>
<