这里我们说说spring aop 事务处理的配置,这里有三种方式实现:
这里要注意一点,,要进行事务管理的方法,必须在方法外进行异常的抛出,这样事务管理器才能接收到,然后进行事务的回滚。如果用try-catch处理异常,将不会进行事务回滚。如果必须使用try-catch的话,必须要throw出去。
事务管理器都是使用的声明式事务处理
注解实现
spring.xml配置
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource" /> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
注意: proxy-target-class=”true” 看自己的需求,是针对类注入还是针对与接口注入,我的项目没有写接口所以加了这个否则这里不用写这个.
注解方式加事务
探索@Transactional注解:
你可以指定传播、隔离级别、超时以及允许和不允许的异常。
@Transactional注解的属性:
propagation:指定事务定义中使用的传播
isolation:设定事务的隔离级别
timeout:指定事务的超时(秒)
readOnly:指定事务的只读性
noRollbackFor:目标方法可抛出的异常所构成的数组,但通知仍会提交事务
rollbackFor:异常所构成的数组,如果目标方法抛出了这些异常,通知就会回滚事务涉及到增删改都需要进行事务管理
@Transactional public Map<String, Object> execCwsDayExec() throws Exception{ //执行存储过程 Map<String, Object> params = new HashMap<String, Object>(); try { params.put("iResultCode", 0); params.put("iResultName",""); sqlSession.update(super.DOMAIN_NAME+".execCwsDayExec",params); } catch (Exception e) { logger.error("执行日终存储过程发生错误:{}", e.getMessage(), e); throw e;//非只读事务,如果要try-catch的话,必须throw, 否则事务异常捕捉不到,事务也不会回滚. } return params; }
查询不写事务或者只读事务都可以的
@Transactional(readOnly=true) public CwsDayChange getCurrDayChange() { List<CwsDayChange> list=sqlSession.selectList(DOMAIN_NAME + ".selectAll"); if (list.size() > 0) return list.get(0); else return null; }
使用切面管理事务
spring.xml配置
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <aop:config> <aop:pointcut expression="execution(public * com.ttcity.portal.service..*.*(..))" id="bussinessServices" /> <aop:advisor pointcut-ref="bussinessServices" advice-ref="txAdvice" /> </aop:config> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="select*" read-only="true" /> <tx:method name="query*" read-only="true" /> <tx:method name="find*" read-only="true" /> <tx:method name="get*" read-only="true" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="modify*" propagation="REQUIRED" /> <tx:method name="del*" propagation="REQUIRED" /> </tx:attributes> </tx:advice>
配置说明
切面的关键在于execution(public * com.ttcity.portal.service...(..))的配置,主要说所有返回值的public方法且包名前缀是com.ttcity.portal.service的进行AOP拦截加事务。
而至于事务是只读还是非只读在于
< tx:method name=”select*” read-only=”true” />(只读性) 和< tx:method name=”del*” propagation=”REQUIRED” />(事务性),name的主要作用是函数的前缀,这样就可以拦截切面方法且方法名为select开头的为只读事务,而del开头事务性拦截。
基于SpringAOP的拦截器(主要利用BeanNameAutoProxyCreator自动创建事务代理)
<!--声明式事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 配置一个事务拦截 --> <bean id="trxInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager" /> <property name="transactionAttributes"> <props> <prop key="insert*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable</prop> <prop key="del*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable</prop> <prop key="add*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable</prop> <prop key="query*">PROPAGATION_SUPPORTS,readOnly</prop> <prop key="select*">PROPAGATION_SUPPORTS,readOnly</prop> </props> </property> </bean> <!-- 自动装配事务到bean --> <bean id="autoTrx" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>*BS</value> </list> </property> <property name="interceptorNames"> <list> <value>trxInterceptor</value> </list> </property> </bean>
我们来说下这个配置,这个配置文件主要要关心
< property name=”transactionAttributes”>节点,下面的props内容主要是增加哪些方法名需要进行什么样的事务处理。例如:<prop key="insert*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,-Throwable</prop>
是说方法名为insert开头方法进行异常事务处理如果发生异常则需要回滚。
<prop key="query*">PROPAGATION_SUPPORTS,readOnly</prop>
这段代码作用是以query开头方法为只读事务。
到这里我们只知道给哪些方法加事务,但是还不知道哪个类里的方法,这里需要用到BeanNameAutoProxyCreator的相关配置,这个配置会自动装配bean:
<property name="beanNames"> <list> <value>*BS</value> </list> </property>
这段配置作用是拦截以BS结尾的类名,这样我们自动装配bean的配置就写好了。