框架學習之Spring的事務管理

一.事務

    1. 事務:指的是邏輯上一組操作,組成這個事務的各個執行單元,要麼一起成功,要麼一起失敗!
    2. 事務的特性
        * 原子性
        * 一致性
        * 隔離性
        * 持久性
    
    3. 如果不考慮隔離性,引發安全性問題
        * 讀問題:
            * 髒讀:
            * 不可重複讀:
            * 虛讀:
        
        * 寫問題:
            * 丟失更新:
    
    4. 如何解決安全性問題
        * 讀問題解決,設置數據庫隔離級別
        * 寫問題解決可以使用 悲觀鎖和樂觀鎖的方式解決

二.Spring框架的JDBC模板技術

    1. Spring框架中提供了很多持久層的模板類來簡化編程,使用模板類編寫程序會變的簡單
    2. 提供了JDBC模板,Spring框架提供的
        * JdbcTemplate類
    
    3. Spring框架可以整合Hibernate框架,也提供了模板類
        * HibernateTemplate類

三.JDBC的模板類應用

1. 步驟一:創建數據庫的表結構
        create database spring_day03;
        use spring_day03;
        create table t_account(
            id int primary key auto_increment,
            name varchar(20),
            money double
        );
    
    2. 引入開發的jar包
        * 先引入IOC基本的6個jar包
            com.springsource.org.apache.commons.logging-1.1.1.jar
            com.springsource.org.apache.log4j-1.2.15.jar
            spring-beans-4.2.4.RELEASE.jar
            spring-context-4.2.4.RELEASE.jar
            spring-core-4.2.4.RELEASE.jar
            spring-expression-4.2.4.RELEASE.jar
        * 再引入Spring-aop的jar包
             spring-aop-4.2.4.RELEASE.jar
             com.springsource.org.aopalliance-1.0.0.jar
             com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
             spring-aspects-4.2.4.RELEASE.jar
            
        * 最後引入JDBC模板需要的jar包
            * MySQL數據庫的驅動包
            * spring-jdbc-4.2.4.RELEASE.jar
            * spring-tx-4.2.4.RELEASE.jar
                * 想要做測試再引入一個測試的包
            spring-test-4.2.4.RELEASE.jar

3.創建Spring的配置文件

       * 步驟一:Spring管理內置的連接池
            <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///spring_day03"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </bean>

----------Spring框架管理開源的連接池--------------------------------------------------------------------------------------

1. 管理DBCP連接池
        * 先引入DBCP的2個jar包   
            在我們下載的Spring開發包中的依賴文件夾中可以找到這兩個jar包
            資料\spring-framework-3.0.2.RELEASE-dependencies 這個依賴的文件夾中找到DBCP的兩個jar包
            * com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar 
            * com.springsource.org.apache.commons.pool-1.5.3.jar
        
        * 編寫配置文件
            <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
                <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///spring_day03"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </bean>
    
    2. 管理C3P0連接池
        * 先引入C3P0的jar包
            在 資料\spring-framework-3.0.2.RELEASE-dependencies 這個依賴的文件夾中找到C3P0這個jar包
            * com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
        
        * 編寫配置文件
            <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
                <property name="driverClass" value="com.mysql.jdbc.Driver"/>
                <property name="jdbcUrl" value="jdbc:mysql:///spring_day03"/>
                <property name="user" value="root"/>
                <property name="password" value="root"/>
            </bean>
    -------------------------------------------------------------------------------------------------------------------------------------
        
        * 步驟二:Spring管理模板類
            <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                <property name="dataSource" ref="dataSource"/>
            </bean>

4.編寫測試程序

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo2 {
				
    @Resource(name="jdbcTemplate")
	private JdbcTemplate jdbcTemplate;
				
    @Test
    public void run2(){
		jdbcTemplate.update("insert into t_account values (null,?,?)", "測試2",10000);
	}
}

四.Spring框架的JDBC模板的簡單操作

1. 增刪改查的操作

@RunWith(SpringJUnit4ClassRunner.class)	@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo3 {
			
	@Resource(name="jdbcTemplate")
	private JdbcTemplate jdbcTemplate;
			
    @Test
	// 插入操作
	public void demo1(){
		jdbcTemplate.update("insert into account values (null,?,?)", "冠希",10000d);
	}
			
	@Test
	// 修改操作
	public void demo2(){
		jdbcTemplate.update("update account set name=?,money =? where id = ?", "思雨",10000d,5);
	}
			
	@Test
	// 刪除操作
	public void demo3(){
		jdbcTemplate.update("delete from account where id = ?", 5);
	}
			
	@Test
	// queryForObject()方法 查詢一條記錄 也就是返回一行記錄  寫一個JavaBean 然後查詢一條數據,幫你封裝進這個JavaBean
	public void demo4(){
	  Account account = jdbcTemplate.queryForObject("select * from account where id = ?", new BeanMapper(), 1);
	  System.out.println(account);
	}
			
	@Test
	// 查詢所有記錄 使用query方法 直接返回一個集合 這個集合裝有所有記錄
	public void demo5(){
	    List<Account> list = jdbcTemplate.query("select * from t_account", new BeanMapper());
		for (Account account : list) {
		    System.out.println(account);
		}
	}
}
		

五.Spring框架的事務管理相關的類和API

   1. PlatformTransactionManager接口        -- 平臺事務管理器.(真正管理事務的類)。該接口有具體的實現類,根據不同的持久層框架,需要選擇不同的實現類!
    2. TransactionDefinition接口            -- 事務定義信息.(事務的隔離級別,傳播行爲,超時,只讀)
    3. TransactionStatus接口                -- 事務的狀態
    
    4. 總結:上述對象之間的關係:平臺事務管理器真正管理事務對象.根據事務定義的信息TransactionDefinition 進行事務管理,在管理事務中產生一些狀態.將狀態記錄到TransactionStatus中
    
    5. PlatformTransactionManager接口中實現類和常用的方法
        1. 接口的實現類
            * 如果使用的Spring的JDBC模板或者MyBatis框架,需要選擇DataSourceTransactionManager實現類
            * 如果使用的是Hibernate的框架,需要選擇HibernateTransactionManager實現類
        
        2. 該接口的常用方法
            * void commit(TransactionStatus status) 
            * TransactionStatus getTransaction(TransactionDefinition definition) 
            * void rollback(TransactionStatus status) 
     
    6. TransactionDefinition
        1. 事務隔離級別的常量
            * static int ISOLATION_DEFAULT                     -- 採用數據庫的默認隔離級別
            * static int ISOLATION_READ_UNCOMMITTED 
            * static int ISOLATION_READ_COMMITTED 
            * static int ISOLATION_REPEATABLE_READ 
            * static int ISOLATION_SERIALIZABLE 
         
        2. 事務的傳播行爲常量(不用設置,使用默認值)
            * 先解釋什麼是事務的傳播行爲:解決的是業務層之間的方法調用!!
            
            * PROPAGATION_REQUIRED(默認值)    -- A中有事務,使用A中的事務.如果沒有,B就會開啓一個新的事務,將A包含進來.(保證A,B在同一個事務中),默認值!!
            * PROPAGATION_SUPPORTS            -- A中有事務,使用A中的事務.如果A中沒有事務.那麼B也不使用事務.
            * PROPAGATION_MANDATORY            -- A中有事務,使用A中的事務.如果A沒有事務.拋出異常.
            
            * PROPAGATION_REQUIRES_NEW(記)-- A中有事務,將A中的事務掛起.B創建一個新的事務.(保證A,B沒有在一個事務中)
            * PROPAGATION_NOT_SUPPORTED        -- A中有事務,將A中的事務掛起.
            * PROPAGATION_NEVER             -- A中有事務,拋出異常.
            
            * PROPAGATION_NESTED(記)        -- 嵌套事務.當A執行之後,就會在這個位置設置一個保存點.如果B沒有問題.執行通過.如果B出現異常,運行客戶根據需求回滾(選擇回滾到保存點或者是最初始狀態)

六.搭建事務管理轉賬案例的環境

1. 步驟一:創建WEB工程,引入需要的jar包
        * IOC的6個包
            com.springsource.org.apache.commons.logging-1.1.1.jar
            com.springsource.org.apache.log4j-1.2.15.jar
            spring-beans-4.2.4.RELEASE.jar
            spring-context-4.2.4.RELEASE.jar
            spring-core-4.2.4.RELEASE.jar
            spring-expression-4.2.4.RELEASE.jar
        * AOP的4個包
             spring-aop-4.2.4.RELEASE.jar
                 com.springsource.org.aopalliance-1.0.0.jar
             com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
             spring-aspects-4.2.4.RELEASE.jar
        * C3P0的1個包
            com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
        * MySQL的驅動包
            mysql-connector-java-5.1.7-bin.jar
        * JDBC模板2個包
             spring-jdbc-4.2.4.RELEASE.jar
             spring-tx-4.2.4.RELEASE.jar
        * 整合JUnit測試包
             spring-test-4.2.4.RELEASE.jar
    
    2. 步驟二:引入配置文件
        * 引入配置文件
            * 引入log4j.properties   日誌的配置文件
            
            * 引入applicationContext.xml   注意約束要寫全了

                <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.xsd
                    http://www.springframework.org/schema/aop
                    http://www.springframework.org/schema/aop/spring-aop.xsd
                    http://www.springframework.org/schema/tx 
                    http://www.springframework.org/schema/tx/spring-tx.xsd">


                        <!-- 配置C3P0的連接池 -->
                <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
                    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
                    <property name="jdbcUrl" value="jdbc:mysql:///spring_day03"/>
                    <property name="user" value="root"/>
                    <property name="password" value="root"/>
                </bean>
    
                    <!-- 配置JDBC的模板類 -->
                <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                    <property name="dataSource" ref="dataSource"/>
                </bean>
    
            </beans>
    3. 步驟三:創建對應的包結構和類
        * com.luo.demo1
            * AccountService
            * AccountServlceImpl
            * AccountDao
            * AccountDaoImpl

4. 步驟四:引入Spring的配置文件,將類配置到Spring中
        <bean id="accountService" class=" com.luo.demo1.AccountServiceImpl">
        </bean>
        
        <bean id="accountDao" class=" com.luo.demo1.AccountDaoImpl">
        </bean>

5. 步驟五:在業務層注入DAO ,在DAO中注入JDBC模板(強調:簡化開發,以後DAO可以繼承JdbcDaoSupport類)

<bean id="accountService" class="com.luo.demo1.AccountServiceImpl">
            <property name="accountDao" ref="accountDao"/>
 </bean>
        
  <bean id="accountDao" class="com.luo.demo1.AccountDaoImpl">
            <property name="dataSource" ref="dataSource"/>
   </bean>

6. 步驟六:編寫DAO和Service中的方法

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
	public void outMoney(String out, double money) {
	    this.getJdbcTemplate().update("update t_account set money = money - ? where name = ?", money,out);
	}
	public void inMoney(String in, double money) {
		this.getJdbcTemplate().update("update t_account set money = money + ? where name = ?", money,in);
	}
}

7. 步驟七:編寫測試程序.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {	
	@Resource(name="accountService")
	private AccountService accountService;
			
	@Test
	public void run1(){
		accountService.pay("張三", "李四", 1000);
	}
}

七.Spring框架的事務管理的分類

1. Spring的編程式事務管理(不推薦使用)
            * 通過手動編寫代碼的方式完成事務的管理(不推薦)
   2. Spring的聲明式事務管理(底層採用AOP的技術)
            * 通過一段配置的方式完成事務的管理(重點掌握註解的方式)

八.事務管理之聲明式事務管理(基於AspectJ的XML方式)

    1. 步驟一:恢復轉賬開發環境 留下C3P0的配置,留下平臺事務管理器的配置,留下service dao 這兩個類的配置    
    2. 步驟二:引入AOP的開發包  
    3. 步驟三:配置事務管理器(Spring使用PlatformTransactionManager接口來管理事務,所以咱們需要使用到他的實現類)
        <!-- 配置事務管理器 -->

            <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                <!--因爲Spring的事務管理器要管理事務,他得拿到數據庫連接對象,因爲只要連接對象才能提交或回滾事務,
                而連接對象又在C3PO連接池中,所以我們把連接池注入到Spring的事務管理器中,讓他幫我們來管理事務. -->

                <property name="dataSource" ref="dataSource"/>
            </bean>

    4.步驟四:在業務層使用模板管理事務:

 // 注入事務模板對象
private TransactionTemplate transactionTemplate;
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
   this.transactionTemplate = transactionTemplate;
 }          
public void pay(final String out, final String in, final double money) {
   transactionTemplate.execute(new TransactionCallbackWithoutResult() {               
      protected void doInTransactionWithoutResult(TransactionStatus status) {
          // 扣錢
           accountDao.outMoney(out, money);
           int a = 10/0;
           // 加錢
          accountDao.inMoney(in, money);
      }
     });
 }

5. 步驟五:配置事務增強  注意順序先配置事務增強,再去配置切面 
        <!-- 配置事務增強 關聯上事務管理器-->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <!--
                    name        :綁定事務的方法名,可以使用通配符,可以配置多個。
                    propagation    :傳播行爲
                    isolation    :隔離級別
                    read-only    :是否只讀 比如查詢可以不用開啓事務,那麼你可以設置爲只讀
                    timeout        :超時信息
                    rollback-for:發生哪些異常回滾.
                    no-rollback-for:發生哪些異常不回滾.
                 -->
                <!-- 哪些方法加事務 tx:method 可以出現多個,你可以配置多個方法 方法名也可以通配 比如 pay* -->
                <tx:method name="pay" propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>

6. 步驟六:配置AOP的切面
        <!-- 配置AOP切面產生代理 -->
        <aop:config>
                <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.luo.demo1.AccountServiceImpl.pay(..))"/>
        </aop:config>

* 注意:如果是自己編寫的切面,使用<aop:aspect>標籤來配置我們寫的切面類,如果是Spring框架提供的切面,配置切面類使用<aop:advisor>標籤。

7. 步驟七:編寫測試類

  @RunWith(SpringJUnit4ClassRunner.class)
  @ContextConfiguration("classpath:applicationContext.xml")
  public class Demo2 {
 
      @Resource(name="accountService")
      private AccountService accountService;
            
      @Test
      public void run1(){
           accountService.pay("冠希", "美美", 1000);
      }
   }

九.事務管理之聲明式事務管理(基於AspectJ的註解方式)

1.步驟1-3同上

2.步驟三:在配置文件中開啓註解事務,把平臺事務管理器傳進去
        <!-- 開啓註解事務 -->
        <tx:annotation-driven transaction-manager="transactionManager"/>

3.步驟四:在業務層上添加一個註解:@Transactional
    @Transactional 這個註解 加在類上,那麼這個類中所有的方法都有事務了
    如果加在某個方法上,那這個方法就有事務了,一般我們加在類上
    @Transactional 加在方法上這個註解裏面裏 有一些屬性就可以設置,比如 隔離級別,事務的傳播行爲等等

4. 編寫測試類

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext3.xml")
public class Demo3 {
			
    @Resource(name="accountService")
	private AccountService accountService;
			
	@Test
	public void run1(){
		accountService.pay("冠希", "美美", 1000);
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章