1.1 Spring事务管理及方式
2014-03-12 23:19
344 查看
Spring是SSH中的管理员,负责管理其它框架,协调各个部分的工作。今天一起学习一下Spring的事务管理。Spring的事务管理分为声明式跟编程式。声明式就是在Spring的配置文件中进行相关配置(XML和注解);编程式就是代码中添加事务,如回滚等。事务拦截器和事务自动代理方式实现原理:像Struts2一样,都是凭借强大的拦截器功能对业务逻辑方法的调用进行拦截,然后又BeanNameAutoProxyCreator自动生成事务代理,最后送事务管理器,统一管理。
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。 DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。
有声明式事务管理和编程式事务管理。
spring是靠AOP的方法拦截异常去判断是否需要事务回滚或提交的。你自己把异常给catch了,又不往上抛出 别人怎么知道你的方法是否执行正常呢。(可以抛出运行时异常就可以)
http://java.chinaitlab.com/Spring/841714_4.html
1.spring在进行声明时事务管理时,通过捕获Service层方法的DataAccessException来提交和回滚事务的,而Service层方法的DataAccessException又是来自调用DAO层方法所产生的异常.
2.我们一般在写DAO层代码时,如果继承JdbcDaoSupport 类,并使用此类所实现的JdbcTemplate来执行数据库操作,此类会自动把低层的SQLException转化成DataAccessException以及DataAccessException的子类.
3.一般在Service层我们可以自己捕获DAO方法所产成的DataAccessException,然后再抛出一个业务方法有意义的异常(ps:此异常最好继承DataAccessException),然后在Web层捕获,这样我们就可以手动编码的灵活实现通过业务方法执行的成功和失败来向用户转发不同的页面.)
下面一起看看两种(XML和注解)声明式事务的具体配置:
声明式事务
XML:
公共配置
[html] view
plaincopyprint?
<!-- 配置sessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation">
<value>classpath:config/hibernate.cfg.xml</value>
</property>
<property name="packagesToScan">
<list>
<value>com.entity</value>
</list>
</property>
</bean>
<!-- 配置事务管理器(声明式的事务) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 配置DAO -->
<bean id="userDao" class="com.dao.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
第一种,使用tx标签方式
[html] view
plaincopyprint?
<!-- 第一种配置事务的方式 ,tx-->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="*" propagation="REQUIRED" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="daoMethod" expression="execution(* com.dao.*.*(..))"/>
<aop:advisor pointcut-ref="daoMethod" advice-ref="txadvice"/>
</aop:config>
expression="execution(* com.dao.*.*(..))"
其中第一个*代表返回值,第二*代表dao下子包,第三个*代表方法名,“(..)”代表方法参数。
第二种,使用代理方式
[html] view
plaincopyprint?
<!-- 第二种配置事务的方式 ,代理-->
<bean id="transactionProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<property name="transactionManager" ref="transactionManager"></property>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="del*">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="*">PROPAGATION_REQUIRED, readOnly</prop>
</props>
</property>
</bean>
<bean id="userDao" parent="transactionProxy">
<property name="target">
<!-- 用bean代替ref的方式-->
<bean class="com.dao.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
</property>
</bean>
将transactionProxy的abstract属性设置为"true",然后将具体的Dao的parent属性设置为"transactionProxy",可以精简代码。
第三种,使用拦截器
[html] view
plaincopyprint?
<!-- 第三种配置事务的方式,拦截器 (不常用)-->
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager"></property>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="del*">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="*">PROPAGATION_REQUIRED, readOnly</prop>
</props>
</property>
</bean>
<bean id="proxyFactory" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
<property name="beanNames">
<list>
<value>*Dao</value>
</list>
</property>
</bean>
Spring事务类型详解:
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
注解:
采用注解的方式,需要注意的是,使用注解的方式需要在Spring的配置文件中加入一句话:<context:annotation-config />,其作用是开启注解的方式。具体配置如下:
[html] view
plaincopyprint?
<!--开启注解方式-->
<context:annotation-config />
<!-- 配置sessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation">
<value>classpath:config/hibernate.cfg.xml</value>
</property>
<property name="packagesToScan">
<list>
<value>com.entity</value>
</list>
</property>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 第四种配置事务的方式,注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
注解文件:
[java] view
plaincopyprint?
package com.dao;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.entity.User;
@Transactional
public class UserDaoImpl_BAK extends HibernateTemplate {
@Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")
public void addUser(User user) throws Exception {
this.save(user);
}
@Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")
public void modifyUser(User user) {
this.update(user);
}
@Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")
public void delUser(String username) {
this.delete(this.load(User.class, username));
}
@Transactional(readOnly=true)
public void selectUser() {
}
}
类头的@Transactional为默认事务配置,如方法没有自己的事务类型,则按默认事务,如有自己的配置,则按自己的配置。
编程式事务
程序中手动添加事务:
Connection conn = null;
UserTransaction tx = null;
try {
tx = getUserTransaction(); //1.获取事务
tx.begin(); //2.开启JTA事务
conn = getDataSource().getConnection(); //3.获取JDBC
//4.声明SQL
String sql = "select * from INFORMATION_SCHEMA.SYSTEM_TABLES";
PreparedStatement pstmt = conn.prepareStatement(sql);//5.预编译SQL
ResultSet rs = pstmt.executeQuery(); //6.执行SQL
process(rs); //7.处理结果集
closeResultSet(rs); //8.释放结果集
tx.commit(); //7.提交事务
} catch (Exception e) {
tx.rollback(); //8.回滚事务
throw e;
} finally {
conn.close(); //关闭连接
}
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。 DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。
有声明式事务管理和编程式事务管理。
spring是靠AOP的方法拦截异常去判断是否需要事务回滚或提交的。你自己把异常给catch了,又不往上抛出 别人怎么知道你的方法是否执行正常呢。(可以抛出运行时异常就可以)
http://java.chinaitlab.com/Spring/841714_4.html
1.spring在进行声明时事务管理时,通过捕获Service层方法的DataAccessException来提交和回滚事务的,而Service层方法的DataAccessException又是来自调用DAO层方法所产生的异常.
2.我们一般在写DAO层代码时,如果继承JdbcDaoSupport 类,并使用此类所实现的JdbcTemplate来执行数据库操作,此类会自动把低层的SQLException转化成DataAccessException以及DataAccessException的子类.
3.一般在Service层我们可以自己捕获DAO方法所产成的DataAccessException,然后再抛出一个业务方法有意义的异常(ps:此异常最好继承DataAccessException),然后在Web层捕获,这样我们就可以手动编码的灵活实现通过业务方法执行的成功和失败来向用户转发不同的页面.)
下面一起看看两种(XML和注解)声明式事务的具体配置:
声明式事务
XML:
公共配置
[html] view
plaincopyprint?
<!-- 配置sessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation">
<value>classpath:config/hibernate.cfg.xml</value>
</property>
<property name="packagesToScan">
<list>
<value>com.entity</value>
</list>
</property>
</bean>
<!-- 配置事务管理器(声明式的事务) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 配置DAO -->
<bean id="userDao" class="com.dao.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
第一种,使用tx标签方式
[html] view
plaincopyprint?
<!-- 第一种配置事务的方式 ,tx-->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="*" propagation="REQUIRED" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="daoMethod" expression="execution(* com.dao.*.*(..))"/>
<aop:advisor pointcut-ref="daoMethod" advice-ref="txadvice"/>
</aop:config>
expression="execution(* com.dao.*.*(..))"
其中第一个*代表返回值,第二*代表dao下子包,第三个*代表方法名,“(..)”代表方法参数。
第二种,使用代理方式
[html] view
plaincopyprint?
<!-- 第二种配置事务的方式 ,代理-->
<bean id="transactionProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<property name="transactionManager" ref="transactionManager"></property>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="del*">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="*">PROPAGATION_REQUIRED, readOnly</prop>
</props>
</property>
</bean>
<bean id="userDao" parent="transactionProxy">
<property name="target">
<!-- 用bean代替ref的方式-->
<bean class="com.dao.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
</property>
</bean>
将transactionProxy的abstract属性设置为"true",然后将具体的Dao的parent属性设置为"transactionProxy",可以精简代码。
第三种,使用拦截器
[html] view
plaincopyprint?
<!-- 第三种配置事务的方式,拦截器 (不常用)-->
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager"></property>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="del*">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="*">PROPAGATION_REQUIRED, readOnly</prop>
</props>
</property>
</bean>
<bean id="proxyFactory" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
<property name="beanNames">
<list>
<value>*Dao</value>
</list>
</property>
</bean>
Spring事务类型详解:
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
注解:
采用注解的方式,需要注意的是,使用注解的方式需要在Spring的配置文件中加入一句话:<context:annotation-config />,其作用是开启注解的方式。具体配置如下:
[html] view
plaincopyprint?
<!--开启注解方式-->
<context:annotation-config />
<!-- 配置sessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation">
<value>classpath:config/hibernate.cfg.xml</value>
</property>
<property name="packagesToScan">
<list>
<value>com.entity</value>
</list>
</property>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 第四种配置事务的方式,注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
注解文件:
[java] view
plaincopyprint?
package com.dao;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.entity.User;
@Transactional
public class UserDaoImpl_BAK extends HibernateTemplate {
@Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")
public void addUser(User user) throws Exception {
this.save(user);
}
@Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")
public void modifyUser(User user) {
this.update(user);
}
@Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")
public void delUser(String username) {
this.delete(this.load(User.class, username));
}
@Transactional(readOnly=true)
public void selectUser() {
}
}
类头的@Transactional为默认事务配置,如方法没有自己的事务类型,则按默认事务,如有自己的配置,则按自己的配置。
编程式事务
程序中手动添加事务:
Connection conn = null;
UserTransaction tx = null;
try {
tx = getUserTransaction(); //1.获取事务
tx.begin(); //2.开启JTA事务
conn = getDataSource().getConnection(); //3.获取JDBC
//4.声明SQL
String sql = "select * from INFORMATION_SCHEMA.SYSTEM_TABLES";
PreparedStatement pstmt = conn.prepareStatement(sql);//5.预编译SQL
ResultSet rs = pstmt.executeQuery(); //6.执行SQL
process(rs); //7.处理结果集
closeResultSet(rs); //8.释放结果集
tx.commit(); //7.提交事务
} catch (Exception e) {
tx.rollback(); //8.回滚事务
throw e;
} finally {
conn.close(); //关闭连接
}
相关文章推荐
- Spring中基于Annotation方式管理事务与传播行为
- Spring 使用注解方式进行事务管理配置方式
- Spring声明式事务管理的多种方式
- 详细配置说明||Spring 使用注解方式进行事务管理
- Spring系列之 (十五):Spring事务管理方式-声明式事务(注解)
- Spring学习-31:Spring中的事务管理之手动编码的方式
- spring的事务管理有几种方式实现,如何实现
- spring 声明式事务管理的配置方式
- Spring 使用注解方式进行事务管理
- Spring 用注解方式来进行事务管理
- Spring(五)事务管理及其注解方式用法
- Spring 使用注解方式进行事务管理
- Spring整合Mybatis(二)------增加事务管理(编程的方式)
- Spring嵌套事务的两种事务管理配置方式
- spring中注解方式实现声明式事务管理
- 事务有哪些特性?spring的事务管理有几种方式实现,如何实现?spring 中常用的两种事务配置方式以及事务的传播性、隔离级别
- Spring声明式事务管理(基于注解方式实现)
- Spring学习---(5)注解方式实现Spring声明式事务管理
- spring_hibernate_事务管理:xml 方式
- spring框架学习(七)spring管理事务方式之xml配置