聲明式事務管理


1、事務概述
  1) 在JavaEE企業級開發的應用領域,為了保證數據的完整性和一致性,必須引入數據庫事務的概念,所以事務管理是企業級應用程序開發中必不可少的技術。
  2) 事務就是一組由於邏輯上緊密關聯而合並成一個整體(工作單元)的多個數據庫操作,這些操作要么都執行,要么都不執行。
  3) 事務的四個關鍵屬性(ACID)
     ①原子性(atomicity):“原子”的本意是“不可再分”,事務的原子性表現為一個事務中涉及到的多個操作在邏輯上缺一不可。事務的原子性要求事務中的所有操作要么都執行,要么都不執行。
     ②一致性(consistency):“一致”指的是數據的一致,具體是指:所有數據都處於滿足業務規則的一致性狀態。一致性原則要求:一個事務中不管涉及到多少個操作,都必須保證事務執行之前數據是正確的,事務執行之后數據仍然是正確的。如果一個事務在執行的過程中,其中某一個或某幾個操作失敗了,則必須將其他所有操作撤銷,將數據恢復到事務執行之前的狀態,這就是回滾。
     ③隔離性(isolation):在應用程序實際運行過程中,事務往往是並發執行的,所以很有可能有許多事務同時處理相同的數據,因此每個事務都應該與其他事務隔離開來,防止數據損壞。隔離性原則要求多個事務在並發執行過程中不會互相干擾。
     ④持久性(durability):持久性原則要求事務執行完成后,對數據的修改永久的保存下來,不會因各種系統錯誤或其他意外情況而受到影響。通常情況下,事務對數據的修改應該被寫入到持久化存儲器中
2、 Spring事務管理
  2-1編程式事務管理
    1) 使用原生的JDBC API進行事務管理
       ①獲取數據庫連接Connection對象
       ②取消事務的自動提交
       ③執行操作
       ④正常完成操作時手動提交事務
       ⑤執行失敗時回滾事務
       ⑥關閉相關資源
    2) 評價
         使用原生的JDBC API實現事務管理是所有事務管理方式的基石,同時也是最典型 的編程式事務管理。編程式事務管理需要將事務管理代碼嵌入到業務方法中來控制事務 的提交和回滾。在使用編程的方式管理事務時,必須在每個事務操作中包含額外的事務 管理代碼。相對於核心業務而言,事務管理的代碼顯然屬於非核心業務,如果多個模塊 都使用同樣模式的代碼進行事務管理,顯然會造成較大程度的代碼冗余。
  2-2聲明式事務管理
     大多數情況下聲明式事務比編程式事務管理更好:它將事務管理代碼從業務方法中分離出來,以聲明的方式來實現事務管理。
     事務管理代碼的固定模式作為一種橫切關注點,可以通過AOP方法模塊化,進而借助Spring AOP框架實現聲明式事務管理。
     Spring在不同的事務管理API之上定義了一個抽象層,通過配置的方式使其生效,從而讓應用程序開發人員不必了解事務管理API的底層實現細節,就可以使用Spring的事務管理機制。
 Spring既支持編程式事務管理,也支持聲明式的事務管理。
  2-3 Spring提供的事務管理器
     Spring從不同的事務管理API中抽象出了一整套事務管理機制,讓事務管理代碼從特定的事務技術中獨立出來。開發人員通過配置的方式進行事務管理,而不必了解其底層是如何實現的。
     Spring的核心事務管理抽象是它為事務管理封裝了一組獨立於技術的方法。無論使用Spring的哪種事務管理策略(編程式或聲明式),事務管理器都是必須的。
     事務管理器可以以普通的bean的形式聲明在Spring IOC容器中。
  2-4 事務管理器的主要實現
    1) DataSourceTransactionManager:在應用程序中只需要處理一個數據源,而且通過JDBC存取。
    2) JtaTransactionManager:在JavaEE應用服務器上用JTA(Java Transaction API)進行事務管理
    3) HibernateTransactionManager:用Hibernate框架存取數據庫

 3、實現步驟

1)配置文件

<?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"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <context:component-scan base-package="com.atguigu.book"></context:component-scan>
    
    <!-- 引入屬性文件 -->
    <!-- <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="db.properties"></property>
    </bean> -->
    
    <!-- 引入屬性文件 -->
    <context:property-placeholder location="db.properties"/>

    <!-- 創建數據源 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!-- 通過數據源配置JdbcTemplate -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 配置事務管理器,事務依賴於數據源所產生的連接對象,只有連接對象創建成功了才能夠處理事務 -->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 開啟注解驅動,即對事務相關的注解進行掃描,解析含義並執行功能 -->
    <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
    
</beans>

2)在需要進行事務控制的方法上加注解 @Transactional

package com.atguigu.book_xml.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.atguigu.book_xml.dao.BookDao;
import com.atguigu.book_xml.exception.MyException;
import com.atguigu.book_xml.service.BookService;

@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao dao;
    
    @Transactional
    public void buyBook(String bid, String uid) {
        /*try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }*/
        Integer price = dao.selectPrice(bid);
        dao.updateSt(bid);
        dao.updateBalance(uid, price);
    }
}

 

 

 

 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM