1.什麼是事務?
事務是邏輯上的一組操做,這組操做要麼所有成功,要麼所有失敗html
2.事物具備四大特性ACID
說到事務,就不得不說其4大特性,主要以下
原子性:(atomicity)
原子性指的是事務是一個不可分割的工做單位,事務中的操做要麼所有發生,要麼都不發生
(就像物理中,原子是最小不可分割的單位)
一致性:(consistency)
一致性指的是事務先後數據的完整性必須保持一致(好比說,轉帳:張三帳戶有2000元,李四帳戶有2000元,一共4000元
張三項李四轉帳2000元后,一共仍是4000元)
事務必須是使數據庫從一個一致性狀態變到另外一個一致性狀態。一致性與原子性是密切相關的
隔離性:(isolation)
隔離性指的是多個用戶併發訪問數據庫是,一個用戶的事務不能被其餘用戶的事務
干擾,多個併發事務之間相互隔離
持久性:(durability)。
持久性指的是一個事務一旦被提交,他對數據庫中的數據的改變是永久的,即便數據庫故障
也不該該對其有任何影響java
3.Spring中事務的管理
Spring中主要提供瞭如下3個接口來對事務進行管理
PlatformTransactionManager 平臺事務管理器
主要用於事務的提交,回滾等說明
TransactionDefintion 事務定義信息(隔離,傳播,超時,只讀)
主要用於事務的隔離,傳播,只讀等說明
TransactionStatus 事務具體運行狀態
是不是一個新的事務,是否有保存點,事務是否完成等說明
大體的運行過程:
首先經過TransactionDefinition定義了事務(隔離,傳播,超時,只讀)等信息後,再交給PlatformTransactionManager平臺事務管理器進行真正的事務管理,以後事務會產生一些相應的狀態,以後就會保存到TransactionStatus中。
3.1平臺事務管理器PlatformTransactionManager
主要定義了各個不一樣的數據庫平臺的一些接口,針對不一樣的數據庫平臺進行事務管理
org.springframework.jdbc.datasource.DataSourceTransactionManager
使用jdbc或Mybatis進行持久化時使用
org.springframework.orm.hibernate3.HibernateTransactionManager使用Hibernate3.0版本進行持久化數據時使用
org.springframework.orm.jdo.JdoTransactionManager 持久化機制爲jdao
org.springframework.orm.jpa.JpaTransactionManager 使用jpa進行持久化
org.springframework.transaction.jta.JtaTransactionManager使用JTA來實現事務管理,在一個事務跨越多個資源時必須使用
咱們再使用不一樣的數據庫時候,能夠選擇不一樣事務管理器,還有這裏列舉了一些經常使用的,還有其餘的能夠參見SpringApi說明,也能夠查看在線api: http://tool.oschina.net/apidocs/#S
3.2事務定義信息接口 TransactionDefintion
主要用於聲明事務的傳播行爲,和隔離級別等信息
假如一個事務不去考慮其隔離性,可能會引起以下問題(髒讀,不可重複讀,幻讀)
3.2.1事務的髒讀,不可重複讀,幻讀
髒讀:一個事務讀取到了一個事務 改寫可是未提交的數據,若是這些數據回滾,則讀取到的數據是無效的
不可重複讀:在同一個事物中,屢次讀取同一數據,因爲另一個事務對該數據 修改提交,形成返回的結果不一樣。
幻讀(虛讀):一個事務讀取幾行記錄後,另外一個事務 插入或刪除 了一些記錄,致使再次讀取的返回結果不一樣。
不可重複讀和幻讀,很類似,只是側重點不一樣:
相同點都是一個事務讀取了另外一個提交了的數據
不一樣點在於,不可重複讀側重點在於修改並提提交,幻讀(虛度)在於刪除或添加
能夠參見博文:http://blog.csdn.net/v123411739/article/details/39298127
3.2.2 事務的隔離級別
爲了解決上訴問題,Spring在接口TransactionDefintion中定義了4中隔離級別,以下:
DEFAULT 使用數據默認的隔離級別(由spring根據使用的數據決定)
READ_UNCOMMITED容許你讀取還未提交的改變了的數據(可致使髒讀,幻讀,不可重複讀)
READ_COMMINTED容許你讀取事務已經提交後的數據(可防止髒讀,可是幻讀和不可重複讀是有可能發生的)
REPEATABLE_READ對相同字段的屢次讀取是一致的,除非數據被事務自己改變(可防止髒讀,不可重複讀,當幻讀任然可能發生)
SERIALIZABLE 徹底服從ACID的隔離級別,確保不發生髒讀,幻讀,不可重複讀。這在全部的隔離級別中是最慢的,他是典型的
經過徹底鎖定在事務中設計的數據表來完成的
提示:oracle默認的是:READ_COMMINTEDmysql默認是:REPEATABLE_READ,前邊的3個是咱們常常須要使用的
3.2.3事務的傳播行爲
通常咱們的事務是在業務層中(Service)中使用的,假如遇到比較複雜的業務,須要在一個業務中調用另外一個業務的方法:
以下:
業務邏輯ServiceA中的方法methoda()中的須要與業務邏輯ServiceB中的方法methodb()方法共同完成某個複雜的邏輯
假如都有事務,究竟是使用誰的事務。
事務的傳播行爲,正是爲了解決業務層中的方法相互調用的問題 的。
- <span style="white-space:pre"> </span>ServiceA{
- methoda(){
- dao1.xxmethod();
- serviceB.methodb();
-
- }
- }
-
- ServiceB{
- methodb(){
- dao2.yymethod();
- }
- }
-
- DAO1{
- xxmethod(){
-
- }
- }
-
- DAO2{
- yymethod(){
-
- }
-
- }
Spring的事務定義信息接口TransactionDefintion還定義了以下7中事務傳播行爲常量,咱們能夠分爲3類,(同一事物中,不一樣事務中,嵌套事務中)
類一,兩種在同一事物中
PROPAGATION_REQUIRED--支持當前事務,若是當前沒有事務,就新建一個事務。這是最多見的選擇。(就好比上邊的場景,methoda假若有事務
則使用methoda的使用,假如methoda沒有則新建一個事務)
PROPAGATION_SUPPORTS--支持當前事務,若是當前沒有事務,就以非事務方式執行。(就好比上邊的場景,methoda假若有事務
則使用methoda的使用,假如methoda沒有則不使用事務)
PROPAGATION_MANDATORY--支持當前事務,若是當前沒有事務,就拋出異常。(就好比上邊的場景,methoda假若有事務
則使用methoda的使用,假如methoda沒有則拋出異常)
類二,二者再也不同一個事物中
PROPAGATION_REQUIRES_NEW--新建事務,若是當前存在事務,把當前事務掛起。(就好比上邊的場景,methoda假若有事務掛起該事物
不使用,而methodb新建一個事務)
PROPAGATION_NOT_SUPPORTED--以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。(就好比上邊的場景,methoda假若有事務掛起該事物
不使用,而methodb不使用事務)
PROPAGATION_NEVER--以非事務方式執行,若是當前存在事務,則拋出異常。(就好比上邊的場景,methoda假若有事務則拋出異常)
類三嵌套事務中
PROPAGATION_NESTED 若是當前事務存在,則嵌套事務執行(若是在執行methoda完成的時候,就會使用事務設置一個保存點,再執行methodb,假如methodb沒有異常,他們就一塊兒提交了,若是
發生了異常,你可根據本身的設定你可選擇回滾到保存點位置,也能夠回滾到最初的狀態)
3.3 事務具體運行狀態接口 TransactionStatus
裏邊主要定義了事務運行過程的一些具體狀態(如是不是新的事務,是否只讀,是否設置保存點)等等,這些都是能夠得到的
4.Spring中的事務實現方式
Spring主要經過以下兩種方式進行事務管理
-編程式事務管理
主要經過TransactionTemplate手動管理事務,在實際開發中不多使用
-使用XML配置聲明
主要經過Spring的AOP實現的,在開發中推薦使用(代碼入侵性小)
4.1Spring的編程式事務管理
所謂編程式事務指的是經過編碼方式實現事務,即相似於JDBC編程實現事務管理。
管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。
對於編程式事務管理,spring推薦使用TransactionTemplate。
這裏咱們經過轉帳的小案例來實現:
account帳戶表:
- create table account(
- id number(20) primary key,
- name varchar2(20),
- money number
- );
-
- insert into account values(1,'張三',1000);
- insert into account values(2,'李四',1000);
- insert into account values(3,'王五',1000);
外部文件db.properties
- jdbc.driver=oracle.jdbc.driver.OracleDriver
- jdbc.url=jdbc:oracle:thin:@localhost:1521:XE
- jdbc.username=xxx
- jdbc.password=xxx
配置文件applicationContext.xml
- <?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:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd">
-
-
- <context:property-placeholder location="classpath:db.properties"/>
-
-
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
- <property name="driverClass">
- <value>${jdbc.driver}</value>
- </property>
- <property name="jdbcUrl">
- <value>${jdbc.url}</value>
- </property>
- <property name="user">
- <value>${jdbc.username}</value>
- </property>
- <property name="password">
- <value>${jdbc.password}</value>
- </property>
- </bean>
-
-
- <bean id="accountService" class="com.xxx.spring.chap5.service.impl.AccountServiceImpl">
- <property name="accountDao" ref="accountDao"></property>
-
- <property name="transactionTemplate" ref="transactionTemplate"></property>
- </bean>
-
- <bean id="accountDao" class="com.xx.spring.chap5.dao.impl.AccountDaoImpl">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
-
-
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
-
-
- <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
- <property name="transactionManager" ref="transactionManager"></property>
- </bean>
- </beans>
Service:業務邏輯接口
- public interface AccountService {
-
-
- public void transfer(String out,String in,Double money);
-
- }
Service業務邏輯實現
- import org.springframework.transaction.TransactionStatus;
- import org.springframework.transaction.support.TransactionCallbackWithoutResult;
- import org.springframework.transaction.support.TransactionTemplate;
- import com.xxx.spring.chap5.dao.AccountDao;
- import com.xxx.spring.chap5.service.AccountService;
- public class AccountServiceImpl implements AccountService {
-
- private AccountDao accountDao;
-
- private TransactionTemplate transactionTemplate;
-
- public TransactionTemplate getTransactionTemplate() {
- return transactionTemplate;
- }
-
- public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
- this.transactionTemplate = transactionTemplate;
- }
-
- public AccountDao getAccountDao() {
- return accountDao;
- }
-
- public void setAccountDao(AccountDao accountDao) {
- this.accountDao = accountDao;
- }
-
- @Override
- public void transfer(final String out, final String in, final Double money) {
-
-
- transactionTemplate.execute(new TransactionCallbackWithoutResult() {
- @Override
- protected void doInTransactionWithoutResult(TransactionStatus arg0) {
- accountDao.outMoney(out, money);
- accountDao.inMoney(in, money);
- }
- });
- }
-
- }
持久層Dao層接口
- public interface AccountDao {
-
-
- public void outMoney(String out,Double money);
-
-
- public void inMoney(String in,Double money);
-
- }
持久層Dao接口實現
- import org.springframework.jdbc.core.support.JdbcDaoSupport;
- import com.briup.spring.chap5.dao.AccountDao;
- public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
-
- @Override
- public void outMoney(String out, Double money) {
- String sql = "update account set money = money - ? where name = ?";
- this.getJdbcTemplate().update(sql, money,out);
- }
-
- @Override
- public void inMoney(String in, Double money) {
- String sql = "update account set money = money + ? where name = ?";
- this.getJdbcTemplate().update(sql, money,in);
- }
-
- }
測試:
- import org.junit.Test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import com.xxx.spring.chap5.service.AccountService;
- public class SpringTransactionTest {
-
- @Test
- public void test1() throws Exception {
- ApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap5/applicationContext.xml");
- AccountService accountService = ac.getBean("accountService",AccountService.class);
- accountService.transfer("張三", "李四", 200.0);
- }
- }
數據庫查詢結果
- 1 張三 800
- 2 李四 1200
- 3 王五 1000
假如Service層轉帳接口出現異常
- @Override
- public void transfer(final String out, final String in, final Double money) {
-
-
- transactionTemplate.execute(new TransactionCallbackWithoutResult() {
- @Override
- protected void doInTransactionWithoutResult(TransactionStatus arg0) {
- accountDao.outMoney(out, money);
- int i = 1/0;
- accountDao.inMoney(in, money);
- }
- });
- }
會發生異常java.lang.ArithmeticException: / by zero...
錢也不會轉過去
4.2Spring中聲明式事務管理
管理創建在AOP之上的。其本質是對方法先後進行攔截,而後在目標方法開始以前建立或者加入一個事務,
在執行完目標方法以後根據執行狀況提交或者回滾事務。聲明式事務最大的優勢就是不須要經過編程的方式管理事務,
這樣就不須要在業務邏輯代碼中摻瑣事務管理的代碼,只需在配置文件中作相關的事務規則聲明
(或經過基於@Transactional註解的方式),即可以將事務規則應用到業務邏輯中。
這裏主要說了解3中實現(基於代理實現,基於AspectJ實現,基於註解實現)
4.2.1聲明式事務管理-基於代理實現
這種方式,主要是使用TransactionProxyFactoryBean代理攔截器實現,經過配置事務代理器從而實現事務管理
配置文件:applicationContext2.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- <span style="white-space:pre"> </span>xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd">
-
-
- <context:property-placeholder location="classpath:db.properties"/>
-
-
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
- <property name="driverClass">
- <value>${jdbc.driver}</value>
- </property>
- <property name="jdbcUrl">
- <value>${jdbc.url}</value>
- </property>
- <property name="user">
- <value>${jdbc.username}</value>
- </property>
- <property name="password">
- <value>${jdbc.password}</value>
- </property>
- </bean>
-
-
- <bean id="accountService2" class="com.xxx.spring.chap5.service.impl.AccountServiceImpl2">
- <property name="accountDao" ref="accountDao2"></property>
- </bean>
-
- <bean id="accountDao2" class="com.xxx.spring.chap5.dao.impl.AccountDaoImpl2">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
-
- <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
-
-
- <bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
-
- <property name="target" ref="accountService2"></property>
-
- <property name="transactionManager" ref="transactionManager"></property>
- <!-- 注入事物的相關屬性,事物的隔離級別,傳播行爲等
- key值爲方法名可使用通配符*
- value值爲
- -->
- <property name="transactionAttributes">
- <props>
- <!-- prop的格式
- key爲方法名,可使用*通配符號
- value值的格式:
- 1. PROPAGATION :事務的傳播行爲
- 2. ISOLATION :事務隔離級別
- 3. readOnly :只讀
- 4. -Exception :發生那些異常回滾
- 5. +Exception :發生那些事務不回滾
-
- 之間使用,號隔開
- -->
- <prop key="trans*">PROPAGATION_REQUIRED</prop>
- </props>
- </property>
- </bean>
- </beans>
Service實現改成以下:
- import org.springframework.transaction.TransactionStatus;
- import org.springframework.transaction.support.TransactionCallbackWithoutResult;
- import org.springframework.transaction.support.TransactionTemplate;
-
- import com.xxx.spring.chap5.dao.AccountDao;
- import com.xxx.spring.chap5.service.AccountService;
-
- public class AccountServiceImpl2 implements AccountService {
-
- private AccountDao accountDao;
-
- private TransactionTemplate transactionTemplate;
-
- public TransactionTemplate getTransactionTemplate() {
- return transactionTemplate;
- }
-
- public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
- this.transactionTemplate = transactionTemplate;
- }
-
- public AccountDao getAccountDao() {
- return accountDao;
- }
-
- public void setAccountDao(AccountDao accountDao) {
- this.accountDao = accountDao;
- }
-
- @Override
- public void transfer(final String out, final String in, final Double money) {
- accountDao.outMoney(out, money);
- accountDao.inMoney(in, money);
- }
- }
Dao層不變
測試類爲:
- @Test
- public void test2() throws Exception {
- ApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap5/applicationContext2.xml");
- AccountService accountService = ac.getBean("accountServiceProxy",AccountService.class);
- accountService.transfer("張三", "李四", 200.0);
- }
查詢結果:
- <span style="white-space:pre"> </span>1 張三 800
- 2 李四 1200
- 3 王五 1000
假如Service中出現異常:
- @Override
- public void transfer(final String out, final String in, final Double money) {
- accountDao.outMoney(out, money);
- int i = 1/0;
- accountDao.inMoney(in, money);
- }
會拋出異常
java.lang.ArithmeticException: / by zero
可是錢沒有多,也沒有少,意思是本次操做失敗會,保證帳戶的安全
4.2.2聲明式事務管理-基於AspectJ實現
SpringAOP中能夠經過在xml文件中配置事務通知來對事務進行管理,這是一種更經常使用的方式
配置文件:applicationContext3.xml
- <?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:context="http://www.springframework.org/schema/context"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd">
-
-
- <context:property-placeholder location="classpath:db.properties" />
-
-
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
- <property name="driverClass">
- <value>${jdbc.driver}</value>
- </property>
- <property name="jdbcUrl">
- <value>${jdbc.url}</value>
- </property>
- <property name="user">
- <value>${jdbc.username}</value>
- </property>
- <property name="password">
- <value>${jdbc.password}</value>
- </property>
- </bean>
-
-
- <bean id="accountService2" class="com.xxx.spring.chap5.service.impl.AccountServiceImpl2">
- <property name="accountDao" ref="accountDao2"></property>
- </bean>
-
- <bean id="accountDao2" class="com.xxx.spring.chap5.dao.impl.AccountDaoImpl2">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
-
- <bean name="transactionManager"
- class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
-
-
- <tx:advice id="txAdvice" transaction-manager="transactionManager">
-
- <tx:attributes>
- <!-- 設置各類方法的
- propagation 爲傳播行爲
- isolation 事務的隔離級別
- read-only 設置之都屬性
- rollback-for 發生生麼異常回滾
- no-rollback-for 發生那些異常不回滾
- -->
- <tx:method name="tran*" propagation="REQUIRED" read-only="true" />
- <tx:method name="get*" propagation="REQUIRED" read-only="true" />
- <tx:method name="find*" propagation="REQUIRED" read-only="true" />
- <tx:method name="save*" propagation="REQUIRED" read-only="false"
- rollback-for="java.lang.Exception" />
- <tx:method name="insert*" propagation="REQUIRED" read-only="false"
- rollback-for="java.lang.Exception" />
- <tx:method name="update*" propagation="REQUIRED" read-only="false"
- rollback-for="java.lang.Exception" />
- <tx:method name="delete*" propagation="REQUIRED" read-only="false"
- rollback-for="java.lang.Exception" />
- <tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
- </tx:attributes>
- </tx:advice>
-
-
- <aop:config>
-
- <aop:pointcut
- expression="execution(* com.xxx.spring.chap5.service.impl.AccountServiceImpl2.*(..))"
- id="pointcut" />
-
- <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
- </aop:config>
- </beans>
Service實現
- import org.springframework.transaction.annotation.Propagation;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.transaction.support.TransactionTemplate;
- import com.xxx.spring.chap5.dao.AccountDao;
- import com.xxx.spring.chap5.service.AccountService;
-
- public class AccountServiceImpl2 implements AccountService {
-
- private AccountDao accountDao;
-
- private TransactionTemplate transactionTemplate;
-
- public TransactionTemplate getTransactionTemplate() {
- return transactionTemplate;
- }
-
- public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
- this.transactionTemplate = transactionTemplate;
- }
-
- public AccountDao getAccountDao() {
- return accountDao;
- }
- public void setAccountDao(AccountDao accountDao) {
- this.accountDao = accountDao;
- }
- @Override
- public void transfer(final String out, final String in, final Double money) {
- accountDao.outMoney(out, money);
- accountDao.inMoney(in, money);
- }
-
- }
測試:
- @Test
- public void test3() throws Exception {
- ApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap5/applicationContext3.xml");
- AccountService accountService = ac.getBean("accountService2",AccountService.class);
- accountService.transfer("張三", "李四", 200.0);
- }
查詢結果:
- 1 張三 800
- 2 李四 1200
- 3 王五 1000
4.2.3聲明式事務管理-基於註解實現
這種也是一種比較常見的使用,主要在xml文件中開始事務註解後,在須要使用事務的業務中添加@Transactionl註解
能夠參見:http://www.cnblogs.com/younggun/archive/2013/07/16/3193800.html
配置文件:applicationContext4.xml
- <?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:context="http://www.springframework.org/schema/context"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd">
-
-
- <context:property-placeholder location="classpath:db.properties" />
-
-
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
- <property name="driverClass">
- <value>${jdbc.driver}</value>
- </property>
- <property name="jdbcUrl">
- <value>${jdbc.url}</value>
- </property>
- <property name="user">
- <value>${jdbc.username}</value>
- </property>
- <property name="password">
- <value>${jdbc.password}</value>
- </property>
- </bean>
-
-
- <bean id="accountService2" class="com.xxx.spring.chap5.service.impl.AccountServiceImpl2">
- <property name="accountDao" ref="accountDao2"></property>
- </bean>
-
- <bean id="accountDao2" class="com.xxx.spring.chap5.dao.impl.AccountDaoImpl2">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
-
- <bean name="transactionManager"
- class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
-
-
- <tx:annotation-driven transaction-manager="transactionManager"/>
- </beans>
Sservice業務層實現:
- import org.springframework.transaction.annotation.Propagation;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.transaction.support.TransactionTemplate;
- import com.xxx.spring.chap5.dao.AccountDao;
- import com.xxx.spring.chap5.service.AccountService;
- @Transactional(propagation=Propagation.REQUIRED,readOnly=true,rollbackFor={RuntimeException.class, Exception.class})
- public class AccountServiceImpl2 implements AccountService {
-
- private AccountDao accountDao;
- public AccountDao getAccountDao() {
- return accountDao;
- }
-
- public void setAccountDao(AccountDao accountDao) {
- this.accountDao = accountDao;
- }
- @Override
- public void transfer(final String out, final String in, final Double money) {
- accountDao.outMoney(out, money);
- accountDao.inMoney(in, money);
- }
-
- }
測試:
- @Test
- public void test4() throws Exception {
- ApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap5/applicationContext4.xml");
- AccountService accountService = ac.getBean("accountService2",AccountService.class);
- accountService.transfer("張三", "李四", 200.0);
- }
查詢結果:
- 1 張三 800
- 2 李四 1200
- 3 王五 1000