亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

Spring中事務管理的四種方法(銀行轉賬為例)

2024-07-14 08:40:49
字體:
來源:轉載
供稿:網友

前言

本文配套示例代碼下載地址(完整可運行,含sql文件,下載后請修改數據庫配置):點擊這里下載

一、事務的作用

  將若干的數據庫操作作為一個整體控制,一起成功或一起失敗。

  原子性:指事務是一個不可分割的工作單位,事務中的操作要么都發生,要么都不發生。

  一致性:指事務前后數據的完整性必須保持一致。

  隔離性:指多個用戶并發訪問數據庫時,一個用戶的事務不能被其他用戶的事務所干擾,多個并發事務之間數據要相互隔離。

  持久性:指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,即時數據庫發生故障也不應該對其有任何影響。

二、Spring事務管理高層抽象主要包括3個接口

  --Platform TransactionManager 事務管理器(提交、回滾事務)

     Spring為不同的持久化框架提供了不同的Platform TransactionManager接口實現。如:

        使用Spring JDBC或iBatis進行持久化數據時使用DataSourceTransactionManager

        使用Hibernate3.0版本進行持久化數據時使用HibernateTransactionManager

  --TransactionDefinition 事務定義信息(隔離、傳播、超時、只讀)

        臟讀:一個事務讀取了另一個事務改寫但還未提交的數據,如果這些數據被回滾,則讀到的數據是無效的。

        不可重復讀:在同一事務中,多次讀取同一數據返回的結果有所不同。

        幻讀:一個事務讀取了幾行記錄后,另一個事務插入一些記錄,幻讀就發生了。再后來的查詢中,第一個事務就會發現有些原來沒有的記錄。

        事務隔離級別:(五種)

  •     DEFAULT--使用后端數據庫默認的隔離級別(Spring中的選擇項)
  •     READ_UNCOMMITED--允許你讀取還未提交的改變了的數據??赡軐е屡K、幻、不可重復讀
  •     READ_COMMITTED--允許在并發事務已經提交后讀取。可防止臟讀,但幻讀和不可重復讀仍可發生
  •     REPEATABLE_READ--對相同字段的多次讀取是一致的,除非數據被事務本身改變。可防止臟、不可重復讀,但幻讀仍可能發生
  •     SERIALIZABLE--完全服從ACID的隔離級別,確保不發生臟、幻、不可重復讀。這在所有的隔離級別中是最慢的,它是典型的通過完全鎖定在事務中涉及的數據表來完成的

    其中,MySQL默認采用REPEATABLE_READ隔離級別;Oracle默認采用READ_COMMITTED隔離級別

        事務傳播行為:(七種)

  •     REQUIRED--支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。
  •     SUPPORTS--支持當前事務,如果當前沒有事務,就以非事務方式執行。
  •     MANDATORY--支持當前事務,如果當前沒有事務,就拋出異常。
  •     REQUIRES_NEW--新建事務,如果當前存在事務,把當前事務掛起。
  •     NOT_SUPPORTED--以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
  •     NEVER--以非事務方式執行,如果當前存在事務,則拋出異常。
  •     NESTED--如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則進行與REQUIRED類似的操作。擁有多個可以回滾的保存點,內部回滾不會對外部事務產生影響。只對DataSourceTransactionManager有效

  --TransactionStatus 事務具體運行狀態

三、Spring提供了以下方法控制事務

  a.編程式事務管理(基于Java編程控制,很少使用)--見demo1包

       利用TransactionTemplate將多個DAO操作封裝起來

  *b.聲明式事務管理(基于Spring的AOP配置控制)

       -基于TransactionProxyFactoryBean的方式.(很少使用)--見demo2包

            需要為每個進行事務管理的類,配置一個TransactionProxyFactoryBean進行增強.

       -基于XML配置(經常使用)--見demo3包

            一旦配置好之后,類上不需要添加任何東西。

            如果Action作為目標對象切入事務,需要在<aop:config>元素里添加proxy-target-class="true"屬性。原因是通知Spring框架采用CGLIB技術生成具有事務管理功能的Action類。

       -基于注解(配置簡單,經常使用)--見demo4包

            在applicationContext.xml中開啟事務注解配置。(applicationContext.xml中只需定義Bean并追加以下元素)

<bean id="txManager" class="..."> <property name="sessionFactory"> </property><tx:annotation-driven transaction-manager="txManager"/>

            在目標組件類中使用@Transactional,該標記可定義在類前或方法前。

四、示例(銀行轉賬)

        --編程式

/**  * @Description:轉賬案例的DAO層接口  *  */ public interface AccountDao {  /**  * @param out  * :轉出賬號  * @param money  * :轉賬金額  */  public void outMoney(String out, Double money);   /**  *  * @param in  * :轉入賬號  * @param money  * :轉賬金額  */  public void inMoney(String in, Double money); } 
/**  * @Description:轉賬案例的DAO層實現類  */ public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {  /**  * @param out  * :轉出賬號  * @param money  * :轉賬金額  */  @Override  public void outMoney(String out, Double money) {  String sql = "update account set money = money-? where name = ?";  this.getJdbcTemplate().update(sql, money, out);  }  /**  * @param in  * :轉入賬號  * @param money  * :轉賬金額  */  @Override  public void inMoney(String in, Double money) {  String sql = "update account set money = money+? where name = ?";  this.getJdbcTemplate().update(sql, money, in);  } } 
/**  * @Description:轉賬案例的業務接口  *  */ public interface AccountService {  /**  * @param out :轉出賬號  * @param in :轉入賬號  * @param money :轉賬金額  */  public void transfer(String out,String in,Double money); } 
/**  * @Description:轉賬案例的業務層實現類  */ public class AccountServiceImpl implements AccountService {  // 注入轉賬的DAO  private AccountDao accountDao;   // 注入事務管理的模板  private TransactionTemplate transactionTemplate;   /**  * @param out  * :轉出賬號  * @param in  * :轉入賬號  * @param money  * :轉賬金額  */  @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);   transactionTemplate.execute(new TransactionCallbackWithoutResult() {   @Override  protected void doInTransactionWithoutResult(   TransactionStatus transactionStatus) {  accountDao.outMoney(out, money);  // int i = 1 / 0;//事務控制,即出現異常,該段內代碼都執行失效  accountDao.inMoney(in, money);  }  });  }   public void setAccountDao(AccountDao accountDao) {  this.accountDao = accountDao;  }   public void setTransactionTemplate(TransactionTemplate transactionTemplate) {  this.transactionTemplate = transactionTemplate;  } } 

applicationContext1.xml

<!-- 引入外部的屬性文件 -->  <context:property-placeholder location="classpath:jdbc.properties"/>   <!-- 配置c3p0連接池 -->  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">  <property name="driverClass" value="${jdbc.driverClass}" />  <property name="jdbcUrl" value="${jdbc.url}" />  <property name="user" value="${jdbc.username}" />  <property name="password" value="${jdbc.password}" />  </bean>   <!-- 配置業務層類 -->  <bean id="accountService" class="com.zs.spring.demo1.AccountServiceImpl">  <property name="accountDao" ref="accountDao" />  <!-- 注入事務管理的模板 -->  <property name="transactionTemplate" ref="transactionTemplate" />  </bean>   <!-- 配置DAO類(簡化,會自動配置JdbcTemplate) -->  <bean id="accountDao" class="com.zs.spring.demo1.AccountDaoImpl">  <property name="dataSource" ref="dataSource" />  </bean>   <!-- 配置DAO類(未簡化) -->  <!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">  <property name="dataSource" ref="dataSource" />  </bean>  <bean id="accountDao" class="com.zs.spring.demo1.AccountDaoImpl">  <property name="jdbcTemplate" ref="jdbcTemplate" />  </bean> -->   <!-- ==================================1.編程式的事務管理=============================================== -->  <!-- 配置事務管理器 -->  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  <property name="dataSource" ref="dataSource" />  </bean>   <!-- 配置事務管理的模板:Spring為了簡化事務管理的代碼而提供的類 -->  <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">  <property name="transactionManager" ref="transactionManager"/>  </bean> 

測試:

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext1.xml") public class TransactionTest {  @Resource(name = "accountService")  private AccountService accountService;   @Test  public void demo1() {  accountService.transfer("aaa", "bbb", 200d);  } } 

    --基于TransactionProxyFactoryBean的方式

public class AccountServiceImpl implements AccountService {  // 注入轉賬的DAO  private AccountDao accountDao;   /**  * @param out  *  :轉出賬號  * @param in  *  :轉入賬號  * @param money  *  :轉賬金額  */  @Override  public void transfer(String out, String in, Double money) {  accountDao.outMoney(out, money);  // int i = 1/0;  accountDao.inMoney(in, money);  }   public void setAccountDao(AccountDao accountDao) {  this.accountDao = accountDao;  } } 

applicationContext2.xml

<!-- 引入外部的屬性文件 -->  <context:property-placeholder location="classpath:jdbc.properties"/>   <!-- 配置c3p0連接池 -->  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">  <property name="driverClass" value="${jdbc.driverClass}" />  <property name="jdbcUrl" value="${jdbc.url}" />  <property name="user" value="${jdbc.username}" />  <property name="password" value="${jdbc.password}" />  </bean>   <!-- 配置業務層類 -->  <bean id="accountService" class="com.zs.spring.demo2.AccountServiceImpl">  <property name="accountDao" ref="accountDao" />  </bean>   <!-- 配置DAO類(簡化,會自動配置JdbcTemplate) -->  <bean id="accountDao" class="com.zs.spring.demo2.AccountDaoImpl">  <property name="dataSource" ref="dataSource" />  </bean>   <!-- ==================================2.使用XML配置聲明式的事務管理(原始方式)=============================================== -->   <!-- 配置事務管理器 -->  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  <property name="dataSource" ref="dataSource" />  </bean>   <!-- 配置業務層的代理 -->  <bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">  <!-- 配置目標對象 -->  <property name="target" ref="accountService" />  <!-- 注入事務管理器 -->  <property name="transactionManager" ref="transactionManager"></property>  <!-- 注入事務的屬性 -->  <property name="transactionAttributes">   <props>   <!--    prop的格式:    * PROPAGATION :事務的傳播行為    * ISOTATION :事務的隔離級別    * readOnly :只讀    * -EXCEPTION :發生哪些異常回滾事務    * +EXCEPTION :發生哪些異常不回滾事務    -->   <prop key="transfer">PROPAGATION_REQUIRED</prop>   <!-- <prop key="transfer">PROPAGATION_REQUIRED,readOnly</prop> -->   <!-- <prop key="transfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop> -->   </props>  </property>  </bean> 

測試:

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext2.xml") public class TransactionTest {  /**  * 一定要注入代理類:因為代理類進行增強的操作  */  // @Resource(name="accountService")  @Resource(name = "accountServiceProxy")  private AccountService accountService;   @Test  public void demo1() {  accountService.transfer("aaa", "bbb", 200d);  } } 

    --基于XML配置

public class AccountServiceImpl implements AccountService {  // 注入轉賬的DAO  private AccountDao accountDao;   /**  * @param out  *  :轉出賬號  * @param in  *  :轉入賬號  * @param money  *  :轉賬金額  */  @Override  public void transfer(String out, String in, Double money) {  accountDao.outMoney(out, money);  // int i = 1/0;  accountDao.inMoney(in, money);   }   public void setAccountDao(AccountDao accountDao) {  this.accountDao = accountDao;  } } 

applicationContext3.xml

<!-- 引入外部的屬性文件 -->  <context:property-placeholder location="classpath:jdbc.properties"/>   <!-- 配置c3p0連接池 -->  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">  <property name="driverClass" value="${jdbc.driverClass}" />  <property name="jdbcUrl" value="${jdbc.url}" />  <property name="user" value="${jdbc.username}" />  <property name="password" value="${jdbc.password}" />  </bean>   <!-- 配置業務層類 -->  <bean id="accountService" class="com.zs.spring.demo3.AccountServiceImpl">  <property name="accountDao" ref="accountDao" />  </bean>   <!-- 配置DAO類(簡化,會自動配置JdbcTemplate) -->  <bean id="accountDao" class="com.zs.spring.demo3.AccountDaoImpl">  <property name="dataSource" ref="dataSource" />  </bean>   <!-- ==================================3.使用XML配置聲明式的事務管理,基于tx/aop=============================================== -->   <!-- 配置事務管理器 -->  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  <property name="dataSource" ref="dataSource" />  </bean>   <!-- 配置事務的通知 -->  <tx:advice id="txAdvice" transaction-manager="transactionManager">  <tx:attributes>   <!--   propagation :事務傳播行為   isolation :事務的隔離級別   read-only :只讀   rollback-for:發生哪些異?;貪L   no-rollback-for :發生哪些異常不回滾   timeout :過期信息   -->   <tx:method name="transfer" propagation="REQUIRED"/>  </tx:attributes>  </tx:advice>   <!-- 配置切面 -->  <aop:config>  <!-- 配置切入點 -->  <aop:pointcut expression="execution(* com.zs.spring.demo3.AccountService+.*(..))" id="pointcut1"/>  <!-- 配置切面 -->  <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>  </aop:config> 

測試:

/**  * @Description:Spring的聲明式事務管理的方式二:基于AspectJ的XML方式的配置  */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext3.xml") public class TransactionTest {  /**  * 一定要注入代理類:因為代理類進行增強的操作  */  @Resource(name = "accountService")  private AccountService accountService;   @Test  public void demo1() {  accountService.transfer("aaa", "bbb", 200d);  } } 

    --基于注解

/**  * @Transactional中的的屬性 propagation :事務的傳播行為 isolation :事務的隔離級別 readOnly :只讀  *   rollbackFor :發生哪些異常回滾 noRollbackFor :發生哪些異常不回滾  *   rollbackForClassName 根據異常類名回滾  */ @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false) public class AccountServiceImpl implements AccountService {  // 注入轉賬的DAO  private AccountDao accountDao;   /**  * @param out  *  :轉出賬號  * @param in  *  :轉入賬號  * @param money  *  :轉賬金額  */  @Override  public void transfer(String out, String in, Double money) {  accountDao.outMoney(out, money);  // int i = 1/0;  accountDao.inMoney(in, money);  }   public void setAccountDao(AccountDao accountDao) {  this.accountDao = accountDao;  } } 

applicationContext4.xml

<!-- 引入外部的屬性文件 -->  <context:property-placeholder location="classpath:jdbc.properties"/>   <!-- 配置c3p0連接池 -->  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">  <property name="driverClass" value="${jdbc.driverClass}" />  <property name="jdbcUrl" value="${jdbc.url}" />  <property name="user" value="${jdbc.username}" />  <property name="password" value="${jdbc.password}" />  </bean>   <!-- 配置業務層類 -->  <bean id="accountService" class="com.zs.spring.demo4.AccountServiceImpl">  <property name="accountDao" ref="accountDao" />  </bean>   <!-- 配置DAO類(簡化,會自動配置JdbcTemplate) -->  <bean id="accountDao" class="com.zs.spring.demo4.AccountDaoImpl">  <property name="dataSource" ref="dataSource" />  </bean>   <!-- ==================================4.使用注解配置聲明式事務============================================ -->   <!-- 配置事務管理器 -->  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  <property name="dataSource" ref="dataSource" />  </bean>   <!-- 開啟注解事務 -->  <tx:annotation-driven transaction-manager="transactionManager"/> 

測試:

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext4.xml") public class TransactionTest {  /**  * 一定要注入代理類:因為代理類進行增強的操作  */  @Resource(name = "accountService")  private AccountService accountService;   @Test  public void demo1() {  accountService.transfer("aaa", "bbb", 200d);  } } 

具體代碼和數據庫文件參考項目完整代碼:

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美亚洲日本网站| 欧美大肥婆大肥bbbbb| 韩国一区二区电影| 91在线观看免费网站| 久久久久久久香蕉网| 色老头一区二区三区在线观看| 日韩高清有码在线| yellow中文字幕久久| 亚洲性av在线| 91精品久久久久久| 国产免费一区二区三区香蕉精| 亚洲一级片在线看| 国产精品青草久久久久福利99| 国产精品吴梦梦| 亚洲自拍小视频| 欧美日韩性生活视频| 777777777亚洲妇女| 欧美成人高清视频| 2019亚洲日韩新视频| 一区二区三区国产在线观看| 欧美重口另类videos人妖| 国产精品亚洲аv天堂网| 超碰97人人做人人爱少妇| 成人免费视频在线观看超级碰| 国产精品igao视频| 久久99精品久久久久久噜噜| 久久五月天综合| 亚洲男人天堂2019| 亚洲精品国产品国语在线| 精品国产一区二区三区四区在线观看| 亚洲人成在线观| 蜜臀久久99精品久久久久久宅男| 国产又爽又黄的激情精品视频| 亚洲国产私拍精品国模在线观看| 亚洲97在线观看| 亚洲电影免费观看高清完整版| 国产亚洲欧洲高清一区| 久久久久久久影院| 中文字幕九色91在线| 欧美精品18videos性欧美| 狠狠综合久久av一区二区小说| 青青草原成人在线视频| 97在线看免费观看视频在线观看| 精品亚洲夜色av98在线观看| 日韩**中文字幕毛片| 日韩经典中文字幕| 国外成人免费在线播放| 久久免费视频在线观看| 久久久久久国产精品| 久久免费视频观看| 欧美xxxx综合视频| 91国偷自产一区二区三区的观看方式| 欧美另类高清videos| 国产精品女视频| 国产欧美一区二区三区视频| 中文字幕久精品免费视频| 欧美极品少妇与黑人| 亚洲二区在线播放视频| 日韩在线视频观看正片免费网站| 成人激情综合网| 国产亚洲精品成人av久久ww| 日韩视频免费在线| 国产精品18久久久久久首页狼| 国产v综合v亚洲欧美久久| 国产精品视频午夜| 日本sm极度另类视频| 欧美久久精品午夜青青大伊人| 亚洲国产日韩欧美在线动漫| 亚洲成人精品在线| 伊人久久久久久久久久| 亚洲国产精品视频在线观看| 中文字幕亚洲情99在线| 亚洲精品第一国产综合精品| 国产精品夫妻激情| 亚洲精品视频免费| 久久影视电视剧免费网站清宫辞电视| 亚洲影视中文字幕| 国产精品白丝jk喷水视频一区| 精品丝袜一区二区三区| 久久免费福利视频| 91精品久久久久久久久| 51精品国产黑色丝袜高跟鞋| 国产精品视频男人的天堂| 美女视频黄免费的亚洲男人天堂| 在线观看中文字幕亚洲| 亚洲中国色老太| 欧美激情视频在线免费观看 欧美视频免费一| 久久九九精品99国产精品| 成人国内精品久久久久一区| 国产一区二区三区在线视频| 久久综合伊人77777蜜臀| 日韩视频中文字幕| 国产精品久久久久久搜索| 裸体女人亚洲精品一区| 国产精品亚洲欧美导航| 91探花福利精品国产自产在线| 91精品国产91久久久久| 亚洲精品色婷婷福利天堂| 成人国产精品久久久久久亚洲| 国产一区二区欧美日韩| 成人黄色激情网| 日韩视频免费大全中文字幕| 色午夜这里只有精品| 欧美午夜性色大片在线观看| 国产亚洲视频在线观看| 69久久夜色精品国产69| 久久九九精品99国产精品| 国产ts一区二区| 国内揄拍国内精品少妇国语| 欧美高清不卡在线| 日韩在线中文字幕| 久久人人97超碰精品888| 91中文字幕一区| 欧美野外猛男的大粗鳮| 国产精品电影观看| 国产中文字幕日韩| 久久免费福利视频| 国产精品久久久久久久久久三级| 福利精品视频在线| 中文.日本.精品| 欧美日韩xxxxx| 国产在线高清精品| 尤物yw午夜国产精品视频| 久久免费视频在线| 午夜精品久久久99热福利| 欧洲永久精品大片ww免费漫画| 久久精品视频在线观看| 精品久久久久人成| 久久777国产线看观看精品| 亚洲国产毛片完整版| 国产精品va在线播放我和闺蜜| 日韩av在线播放资源| 国产日韩在线看| 国产精品av电影| 国产精品视频一区二区三区四| 中文字幕av一区二区三区谷原希美| 日韩精品在线视频美女| 日韩av理论片| 国产欧美欧洲在线观看| 大胆欧美人体视频| 成人精品视频99在线观看免费| 日韩精品亚洲精品| 欧美午夜精品伦理| 精品日韩中文字幕| 亚洲国产精品福利| 国产一区二区av| 免费不卡欧美自拍视频| 久久久久久久久久亚洲| 日韩久久精品成人| 97久久精品在线| 久久精品91久久久久久再现| 95av在线视频| 成人性生交xxxxx网站| 成人黄色生活片| 色偷偷91综合久久噜噜| 国产不卡av在线| 在线看福利67194| 日韩亚洲欧美中文高清在线| 欧美成人一二三| 欧美一级高清免费播放| 国产精品高潮呻吟久久av黑人| 精品成人乱色一区二区| 亚洲激情在线观看视频免费| 久久久免费观看视频|