javascript
Spring学习8-Spring事务管理(AOP/声明式式事务管理)
聲明式事務(wù)的事務(wù)屬性:
一:傳播行為
二:隔離級(jí)別
三:只讀提示
四:事務(wù)超時(shí)間隔
五:異常:指定除去RuntimeException其他回滾異常。
?傳播行為:
所謂事務(wù)的傳播行為是指,如果在開始當(dāng)前事務(wù)之前,一個(gè)事務(wù)上下文已經(jīng)存在,此時(shí)有若干選項(xiàng)可以指定一個(gè)事務(wù)性方法的執(zhí)行行為。
spring的事務(wù)傳播規(guī)則:
| 傳播行為 | 意義 |
| PROPAGATION_REQUIRED | 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。 |
| PROPAGATION_REQUIRES_NEW | 創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。 |
| PROPAGATION_SUPPORTS | 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。 |
| PROPAGATION_NOT_SUPPORTED | 以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。 |
| PROPAGATION_NEVER | 以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常 |
| PROPAGATION_MANDATORY | 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常。 |
| PROPAGATION_NESTED | 如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運(yùn)行;如果當(dāng)前沒有事務(wù),則該取值等價(jià)于TransactionDefinition.PROPAGATION_REQUIRED。 |
隔離級(jí)別:
隔離級(jí)別是指若干個(gè)并發(fā)的事務(wù)之間的隔離程度:
spring的事務(wù)隔離級(jí)別:?
| 隔離級(jí)別 | 含義 |
| ISOLATION_DEFAULT | 這是默認(rèn)值,表示使用底層數(shù)據(jù)庫的默認(rèn)隔離級(jí)別。對(duì)大部分?jǐn)?shù)據(jù)庫而言,通常這值就是ISOLATION_READ_COMMITTED。 |
| ISOLATION_READ_UNCOMMITTED | 該隔離級(jí)別表示一個(gè)事務(wù)可以讀取另一個(gè)事務(wù)修改但還沒有提交的數(shù)據(jù)。該級(jí)別不能防止臟讀和不可重復(fù)讀,因此很少使用該隔離級(jí)別。 |
| ISOLATION_READ_COMMITTED | 該隔離級(jí)別表示一個(gè)事務(wù)只能讀取另一個(gè)事務(wù)已經(jīng)提交的數(shù)據(jù)。該級(jí)別可以防止臟讀,這也是大多數(shù)情況下的推薦值。 |
| ISOLATION_REPEATABLE_READ | 該隔離級(jí)別表示一個(gè)事務(wù)在整個(gè)過程中可以多次重復(fù)執(zhí)行某個(gè)查詢,并且每次返回的記錄都相同。即使在多次查詢之間有新增的數(shù)據(jù)滿足該查詢,這些新增的記錄也會(huì)被忽略。該級(jí)別可以防止臟讀和不可重復(fù)讀。 |
| ISOLATION_SERIALIZABLE | 所有的事務(wù)依次逐個(gè)執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾,也就是說,該級(jí)別可以防止臟讀、不可重復(fù)讀以及幻讀。但是這將嚴(yán)重影響程序的性能。通常情況下也不會(huì)用到該級(jí)別。 |
SessionFlush設(shè)置為none(readOnly);
事務(wù)的只讀屬性是指,對(duì)事務(wù)性資源進(jìn)行只讀操作或者是讀寫操作。所謂事務(wù)性資源就是指那些被事務(wù)管理的資源,比如數(shù)據(jù)源、 JMS資源,以及自定義的事務(wù)性資源等等。如果確定只對(duì)事務(wù)性資源進(jìn)行只讀操作,那么我們可以將事務(wù)標(biāo)志為只讀的,以提高事務(wù)處理的性能。在TransactionDefinition 中以 boolean 類型來表示該事務(wù)是否只讀。
事務(wù)超時(shí)間隔:
所謂事務(wù)超時(shí),就是指一個(gè)事務(wù)所允許執(zhí)行的最長時(shí)間,如果超過該時(shí)間限制但事務(wù)還沒有完成,則自動(dòng)回滾事務(wù)。在TransactionDefinition 中以 int 的值來表示超時(shí)時(shí)間,其單位是秒。
聲明式事務(wù)使用范例:
??二、聲明式事務(wù)配置的5中方式(方式四最常用)
?? 方式一、基于Spring1.x,使用TransactionProxyFactoryBean為每個(gè)Bean生成一個(gè)代理。
????<?xml version="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
???xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
???xmlns:aop="http://www.springframework.org/schema/aop"
???xsi:schemaLocation="http://www.springframework.org/schema/beans
??????????http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
??????????http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
???<bean id="sessionFactory"
???????????class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
???????<property name="configLocation"value="classpath:hibernate.cfg.xml" />
???????<property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/>
???</bean>
???<!-- 定義事務(wù)管理器(聲明式的事務(wù)) -->
???<beanid="transactionManager"??????class="org.springframework.orm.hibernate3.HibernateTransactionManager">
???????<property name="sessionFactory" ref="sessionFactory"/>
???</bean>
??
???<!-- 配置DAO省略 -->
??? <!--*******業(yè)務(wù)邏輯層(是對(duì)各個(gè)DAO層的正面封裝)主要用到<<門面模式>>******-->
????<bean id="fundService"
?????class="com.jack.fund.service.serviceimpl.FundService">
?????<property name="producedao">
??????<ref bean="fundProduceDAO" />
?????</property>
????</bean>
??
????<beanid="fundServiceProxy"
?????class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
?????<!-- 配置事務(wù)管理器 -->
?????<propertyname="transactionManager">
??????<ref bean="transactionManager"/>
?????</property>
?????<!-- 此屬性指定目標(biāo)類本本身是否是代理的對(duì)象,如果目標(biāo)類沒有實(shí)現(xiàn)任何類,就設(shè)為true代表自己 可省略不寫-->
?????<propertyname="proxyTargetClass">
??????<value>false</value>
?????</property>
?????<!-- 代理接口? 可省略不寫-->
?????<propertyname="proxyInterfaces">
??????<value>com.jack.fund.service.IFundService</value>
?????</property>
?????<!-- 目標(biāo)bean -->
?????<property name="target">
??????<ref bean="fundService" />
?????</property>
?????<!-- 配置事務(wù)屬性 -->
?????<propertyname="transactionAttributes">
??????<props>
???????<propkey="delete*">PROPAGATION_REQUIRED</prop>
???????<propkey="add*">PROPAGATION_REQUIRED</prop>
???????<propkey="update*">PROPAGATION_REQUIRED</prop>
???????<propkey="save*">PROPAGATION_REQUIRED</prop>
???????<prop??key="find*">PROPAGATION_REQUIRED,readOnly</prop>
??????</props>
?????</property>
????</bean>
</beans>
????可以看出 它適用于你的庫表比較少的情況下,針對(duì)每一個(gè)功能模塊配置一個(gè)業(yè)務(wù)代理服務(wù)。如果模塊多大話,就顯得代碼有點(diǎn)多了,發(fā)現(xiàn)他們只是稍微一點(diǎn)不一樣。這時(shí)我們就應(yīng)該想到繼承的思想。用第二種方法。
?
方式二、基于Spring1.x,使用TransactionProxyFactoryBean為所有Bean共享一個(gè)代理基類。
???<?xml version="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
???xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
???xmlns:aop="http://www.springframework.org/schema/aop"
???xsi:schemaLocation="http://www.springframework.org/schema/beans
??????????http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
??????????http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
???<bean id="sessionFactory"
???????????class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
???????<property name="configLocation"value="classpath:hibernate.cfg.xml" />
???????<property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/>
???</bean>
???<!-- 定義事務(wù)管理器(聲明式的事務(wù)) -->
???<bean id="transactionManager"
???????class="org.springframework.orm.hibernate3.HibernateTransactionManager">
???????<property name="sessionFactory" ref="sessionFactory"/>
???</bean>
??
????<!--利用繼承的思想簡化配置,要把a(bǔ)bstract="true"-->
????<beanid="transactionBase"???class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
?????lazy-init="true" abstract="true">
?????<!-- 配置事務(wù)管理器 -->
?????<propertyname="transactionManager">
??????<ref bean="transactionManager"/>
?????</property>
?????<!-- 配置事務(wù)屬性 -->
?????<propertyname="transactionAttributes">
??????<props>
???????<propkey="delete*">PROPAGATION_REQUIRED</prop>
???????<propkey="add*">PROPAGATION_REQUIRED</prop>
???????<propkey="update*">PROPAGATION_REQUIRED</prop>
???????<propkey="save*">PROPAGATION_REQUIRED</prop>
???????<propkey="find*">PROPAGATION_REQUIRED,readOnly</prop>
??????</props>
?????</property>
????</bean>
??? <!--而具體的模塊可以簡單的這樣配置。只要指明它的parent(父類)就可以了。父類一般把a(bǔ)bstract="true",因?yàn)樵谌萜骷虞d的時(shí)候不需要初始化,等到用的時(shí)候再有它的子類調(diào)用的時(shí)候,再去初始化。? -->
? <!-- 配置DAO省略-->
???<!--*******業(yè)務(wù)邏輯層(是對(duì)各個(gè)DAO層的正面封裝)主要用到<<門面模式>>******-->
????<bean id="fundService"
?????class="com.jack.fund.service.serviceimpl.FundService">
?????<property name="producedao">
??????<ref bean="fundProduceDAO" />
?????</property>
????</bean>
??? <bean id="fundServiceProxy"parent="transactionBase" >
?????<property name="target">
?????<ref bean="fundService" />
?????</property>
????</bean>
</beans>
這樣配置的話,如果有多個(gè)像fundService這樣模塊時(shí),可以少些很多重復(fù)的代碼。
方式三、基于SpringAOP的攔截器(主要利用BeanNameAutoProxyCreator自動(dòng)創(chuàng)建事務(wù)代理)
<?xml version="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
???xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
???xmlns:aop="http://www.springframework.org/schema/aop"
???xsi:schemaLocation="http://www.springframework.org/schema/beans
??????????http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
??????????http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
???<bean id="sessionFactory"
???????????class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
???????<property name="configLocation"value="classpath:hibernate.cfg.xml" />
???????<property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/>
???</bean>
???<!-- 定義事務(wù)管理器(聲明式的事務(wù)) -->
???<bean id="transactionManager"
???????class="org.springframework.orm.hibernate3.HibernateTransactionManager">
???????<property name="sessionFactory" ref="sessionFactory"/>
???</bean>
??? <bean id="transactionInterceptor"????class="org.springframework.transaction.interceptor.TransactionInterceptor">
???????<property name="transactionManager"ref="transactionManager" />
???????<!-- 配置事務(wù)屬性 -->
?????<propertyname="transactionAttributes">
??????<props>
???????<propkey="delete*">PROPAGATION_REQUIRED</prop>
???????<propkey="add*">PROPAGATION_REQUIRED</prop>
???????<propkey="update*">PROPAGATION_REQUIRED</prop>
???????<propkey="save*">PROPAGATION_REQUIRED</prop>
???????<propkey="find*">PROPAGATION_REQUIRED,readOnly</prop>
??????</props>
?????</property>
???</bean>???
??? <beanclass="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
???????<property name="beanNames">
???????????<list>
???????????<!-- 匹配所有的Service或者某個(gè)具體Service-->
???????????????<value>*Service</value>
???????????</list>
???????</property>
???????<propertyname="interceptorNames">
???????????<list>
???????????????<value>transactionInterceptor</value>
???????????</list>
???????</property>
???</bean>
????<!-- 配置DAO省略 -->
???<!--*******業(yè)務(wù)邏輯層(是對(duì)各個(gè)DAO層的正面封裝)主要用到<<門面模式>>******-->
????<bean id="fundService"
?????class="com.jack.fund.service.serviceimpl.FundService">
?????<property name="producedao">
??????<ref bean="fundProduceDAO" />
?????</property>
????</bean>
</beans>
方式四、基于Spring2.x,使用tx標(biāo)簽配置的攔截器
?<?xml version="1.0"encoding="UTF-8"?>
<beansxmlns="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/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd
??????????http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
? ? <beanid="sessionFactory"?????class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
???????<property name="configLocation"value="classpath:hibernate.cfg.xml" />
???????<property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/>
???</bean>
???<!-- 定義事務(wù)管理器(聲明式的事務(wù)) -->
???<bean id="transactionManager"?class="org.springframework.orm.hibernate3.HibernateTransactionManager">
???????<property name="sessionFactory" ref="sessionFactory"/>
???</bean>
?<!--??定義JDBC的事務(wù)管理器
? ? ?<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
???????<property name="dataSource" ref="dataSource"/>
???</bean>
-->
<!-- 定義切面-->
???<tx:advice id="txAdvice"transaction-manager="transactionManager">
???????<tx:attributes>
???????????<tx:method name="get*" read-only="true"rollback-for="java.lang.Exception"/>
????????????????<!--其他方法設(shè)為如下傳播屬性-->
???????????<tx:method name="*" propagation="REQUIRED"rollback-for="java.lang.Exception"/>?
??????????</tx:attributes>
???</tx:advice>
<!--定義切點(diǎn)和織入-->??
??? <aop:config>
???????<aop:pointcut id="interceptorPointCuts"
???????????expression="execution(* com.spring.service.*.*(..))" />
???????<!-- mgrService和 empService省略?-->
????????<aop:pointcut id="leePointcut"
? ? ?? ? ?expression="bean(mgrService) || bean(empService)" />
???????<aop:advisor advice-ref="txAdvice"
???????????pointcut-ref="interceptorPointCuts"/>
???????<aop:advisor advice-ref="txAdvice"
???????????pointcut-ref=" leePointcut"/>
? ? ?? <!-- 將authority轉(zhuǎn)換成切面Bean
?????????切面Bean的新名稱為:authorityAspect-->
????? ?<aop:aspectid="authorityAspect" ref="authority">
?????????<!--定義一個(gè)Around增強(qiáng)處理,直接指定切入點(diǎn)表達(dá)式
????????????以切面Bean中的authority()方法作為增強(qiáng)處理方法-->
?????????<aop:around pointcut="execution(*org.crazyjava.message.service.impl.*Impl.*Message*(..))"
????????????method="authority"/>
??????</aop:aspect>???
???</aop:config>
<!-- 定義一個(gè)普通Bean實(shí)例,該Bean實(shí)例將進(jìn)行權(quán)限控制-->
???<bean id="authority"
???class="org.crazyjava.message.authority.AuthorityInterceptor"/>? ?
</beans>
?關(guān)于權(quán)限攔截的類AuthorityInterceptor定義如下:
?public class AuthorityInterceptor
{
???//進(jìn)行權(quán)限檢查的方法
??? publicObject authority(ProceedingJoinPoint jp)
?????? throwsjava.lang.Throwable
??? {
?????? HttpSessionsess = null;
??????//獲取被攔截方法的全部參數(shù)
?????? Object[]args = jp.getArgs();
??????//遍歷被攔截方法的全部參數(shù)
?????? for (int i =0 ; i < args.length ; i++ )
?????? {
?????????//找到HttpSession類型的參數(shù)
????????? if (args[i]instanceof HttpSession) sess =
????????????(HttpSession)args[i];
?????? }
??????//取出HttpSession里的user屬性
?????? IntegeruserId = (Integer)sess.getAttribute("user");
??????//如果HttpSession里的user屬性不為null,且大于0
?????? if ( userId!= null && userId >0)
?????? {
????????? //繼續(xù)處理
????????? returnjp.proceed(args);
?????? }
?????? else
?????? {
?????????//如果還未登錄,拋出異常
????????? throw newMessageException("您還沒有登陸,請(qǐng)先登陸系統(tǒng)再執(zhí)行該操作");
?????? }
??? }
}
方式五、注解式聲明事務(wù)(詳見下篇博文)
其實(shí)他們還可以混合使用,方式三和方式四的混合使用:
<?xml version="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
???xmlns:aop="http://www.springframework.org/schema/aop"
???xmlns:tx="http://www.springframework.org/schema/tx"
???xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
???xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
???http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd
???http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!--?? 其他省略
??????********************
??????????? AOP通知
??????********************
????-->
??? <bean id="exception"class="com.etc.advisor.ExceptionAdvisor"></bean>
???<bean id="tx"class="org.springframework.transaction.interceptor.TransactionInterceptor">
??????<constructor-arg index="0">
?????????<ref bean="tm"/>
??????</constructor-arg>
??????<constructor-arg index="1">
?????????<props>
????????????<propkey="*">PROPAGATION_REQUIRED</prop>
?????????</props>
??????</constructor-arg>
???</bean>
???
???<aop:configproxy-target-class="true">
??????<aop:pointcut id="p1" expression="(execution(*com.etc.action.*.execute()))" />
??????<aop:pointcut id="p2" expression="(execution(*com.etc.*.*.*(..)))" />
??????<aop:pointcut id="p3" expression="(execution(*com.etc.service.*.*(..)))" /><!--service的所有方法 -->
??????<aop:advisor advice-ref="tx"pointcut-ref="p1"/>
??????<aop:advisor advice-ref="exception"pointcut-ref="p2"/>
???</aop:config>
</beans>
??三、Spring事務(wù)配置示例
步驟一、配置文件(applicationContext.xml):
???<?xml version="1.0"encoding="UTF-8"?>
?<beansxmlns="http://www.springframework.org/schema/beans"
????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"
????xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
?
????<bean id="userservice"class="com.sunflower.yuan.serviceimp.UserServiceImp">
????????<property name="jdbcTemplate">
????????????<ref bean="jdbcTemplate"/>
????????</property>
????</bean>
????
????<bean id="datasource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
????????<property name="driverClassName"value="com.mysql.jdbc.Driver"></property>
????????<property name="url"value="jdbc:mysql://localhost:3306/mytest"></property>
????????<property name="username"value="root"></property>
????????<property name="password"value="root"></property>
????</bean>
????
????<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
????????<property name="dataSource">
????????????<ref bean="datasource"/>
????????</property>
????</bean>
????
????<bean id="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate">
????????<property name="dataSource">
????????????<ref bean="mydatasource"/>
????????</property>
????</bean>
????
????
????
???? <beanid="transactionAttributeSource"??class="org.springframework.transaction.interceptor.
????????NameMatchTransactionAttributeSource">
????????<property name="properties">
????????????<props>
????????????????<prop key="getMoney">
????????????????????PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-NoMoneyException
????????????????</prop>
????????????</props>
????????</property>
????</bean>
????
????
????<!-- 聲明式事務(wù)管理的代理類-->
????<beanid="userTransaction"???????
? class="org.springframework.transaction.interceptor.??TransactionProxyFactoryBean">
????????<propertyname="proxyInterfaces">
????????????<list>
????????????????<value>com.sunflower.yuan.servicedao.UserService</value>
????????????</list>
????????</property>
????????<property name="target">
????????????<ref bean="userservice"/>
????????</property>
????????<propertyname="transactionManager">
????????????<ref bean="transactionManager"/>
????????</property>
????????<propertyname="transactionAttributeSource">
????????????<refbean="transactionAttributeSource"/>
????????</property>
????</bean>
?</beans>
聲明式事務(wù)管理也是用動(dòng)態(tài)代理模式來實(shí)現(xiàn)的,思想和AOP是一樣的。主要是配置org.springframework.transaction.interceptor.TransactionProxyFactoryBean類。這個(gè)配置和AOP的配置非常相似??梢詫⑹聞?wù)屬性單獨(dú)寫在org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource中,然后再用<propertyname="transactionAttributeSource">引入,也可以直接用<propertyname="transactionAttributes">配置事務(wù)屬性。
<propkey="getMoney">標(biāo)簽中的key="getMoney"表示對(duì)getMoney方法進(jìn)行事務(wù)管理,也可使用通配符get*,表示對(duì)所有g(shù)et前綴的方法進(jìn)行事務(wù)管理。
事務(wù)屬性的配置用","隔開,如下所示:
PROPAGATION, ISOLATION, readonly, -Exception, +Exception
PROPAGATION: 傳播行為
ISOLATION: 隔離級(jí)別
readonly:? 是否為只讀事務(wù)(可選)
(+/-)Exception:? 回滾規(guī)則。如果是"-",遇到指定的Exception,事務(wù)回滾,如果是"+",事務(wù)不回滾。
UserService.java:
public interface UserService {
????public void getMoney(int money, int id) throwsNoMoneyException;
?}
UserServiceImp.java:
package com.sunflower.yuan.serviceimp;
?
?import java.sql.ResultSet;
?import java.sql.SQLException;
?
?importorg.springframework.jdbc.core.JdbcTemplate;
?importorg.springframework.jdbc.core.RowCallbackHandler;
?
?importcom.sunflower.yuan.Exception.NoMoneyException;
?importcom.sunflower.yuan.servicedao.UserService;
?
?
?public class UserServiceImp implementsUserService {
????private JdbcTemplate jdbcTemplate;
?
????public JdbcTemplate getJdbcTemplate() {
????????return jdbcTemplate;
????}
?
????public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
????????this.jdbcTemplate = jdbcTemplate;
????}
?
????@Override
????public void getMoney(int getMoney, int id) throws NoMoneyException{
?
????????String sql = "select money from user where id=?";
????????Object[] params = new Object[] { new Integer(id) };
?
????????MyRowCallbackHandler rowCallBack = newMyRowCallbackHandler();
????????jdbcTemplate.query(sql, params, rowCallBack);
?
????????if (rowCallBack.getMoney() > getMoney) {
????????????sql = "update user set money=? where id=?";
????????????Object[] params2 = new Object[] {
????????????????????rowCallBack.getMoney() - getMoney, new Integer(id) };
????????????jdbcTemplate.update(sql, params2);
????????????throw new NoMoneyException("余額不足");
????????}
?
????}
?
????class MyRowCallbackHandler implements RowCallbackHandler {
????????private int money = 0;
?
????????public int getMoney() {
????????????return money;
????????}
?
????????public void setMoney(int money) {
????????????this.money = money;
????????}
?
????????@Override
????????public void processRow(ResultSet rs) throws SQLException {
????????????this.money = rs.getInt("money");
????????}
????}
?}
這里要注意一點(diǎn),要進(jìn)行事務(wù)管理的方法,必須在方法外進(jìn)行異常的拋出,這樣事務(wù)管理器才能接收到,然后進(jìn)行事務(wù)的回滾。如果用try-catch處理異常,將不會(huì)進(jìn)行事務(wù)回滾。
總結(jié)
以上是生活随笔為你收集整理的Spring学习8-Spring事务管理(AOP/声明式式事务管理)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面向切面(AOP)之Spring接口方式
- 下一篇: spring4声明式事务--01注解方式