Spring事務管理

    springMVC已經愈來愈流行了。如下是對spring事務的一些我的總結。咱們先了解下事務:數據庫事務(Database Transaction) ,是指做爲單個邏輯工做單元執行的一系列操做。 事務處理能夠確保除非事務性單元內的全部操做都成功完成,不然不會永久更新面向數據的資源。經過將一組相關操做組合爲一個要麼所有成功要麼所有失敗的單元,能夠簡化錯誤恢復並使應用程序更加可靠。一個邏輯工做單元要成爲事務,必須知足所謂的ACID(原子性、一致性、隔離性和持久性)屬性。spring

  那麼在spring框架中怎麼使用尼?sql

  一、dataSource,jdbcTemplate配置(默認已經瞭解spring)數據庫

    <!-- 配置jdbcTemplate -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!-- 配置數據源 -->
    <!-- 以dataSource方式使用proxool鏈接池 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" init-method="init" destroy-method="close">
        <property name="name" value="${jdbc.username}" />
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        
        <property name="initialSize" value="${ds.initialSize}" />
        <property name="minIdle" value="${ds.minIdle}" />
        <property name="maxActive" value="${ds.maxActive}" />
        
        <property name="maxWait" value="${ds.maxWait}" />
        <property name="timeBetweenEvictionRunsMillis" value="${ds.timeBetweenEvictionRunsMillis}" />
        <property name="validationQuery" value="SELECT 'x' FROM dual" />
        <property name="connectionProperties" value="oracle.jdbc.ReadTimeout=${oracle.jdbc.ReadTimeout};oracle.net.CONNECT_TIMEOUT=${oracle.net.CONNECT_TIMEOUT}" />
    </bean>

爲了方便修改,採起配置文件的形式。oracle

# 數據庫類型設置(oracle)
ds.dialect=oracle
# Oracle數據庫
jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.username=dreamer
jdbc.password=123qwe
# SQL執行時間超過必定時間則記錄爲慢SQL
ds.slowSqlMillis=3000
# 慢SQL統計日誌輸出
ds.logSlowSql=false
# 合併SQL統計
ds.mergeSql=false
# 初始化時創建物理鏈接的個數
ds.initialSize=1
# 最小鏈接數
ds.minIdle=1
# 容許最大鏈接數,超過了這個鏈接,再有請求時,就排在隊列中等候,最大的等待請求數由maximum-new-connections決定 
ds.maxActive=20
# 獲取鏈接時最大等待時間
ds.maxWait=5000
# 檢測須要關閉的空閒鏈接的間隔時間, 單位是毫秒
ds.timeBetweenEvictionRunsMillis=120000
#oracle jdbc驅動socket超時
oracle.jdbc.ReadTimeout=600000
#oracle jdbc創建新鏈接超時時間
oracle.net.CONNECT_TIMEOUT=6000

而後就是若是簡單的操做數據庫了。示例代碼app

public class JdbcDemo {
    @Autowired
    public JdbcTemplate jdbcTemplate;
    
    public void callP(){
        //調用存儲過程
        jdbcTemplate.execute("{}", new CallableStatementCallback<String>() {

            @Override
            public String doInCallableStatement(CallableStatement stat)
                    throws SQLException, DataAccessException {
                //填參數
                stat.setString(0, "hello");
                ResultSet rs = stat.executeQuery();
                while( rs.next()){
                    rs.getString(0);
                    //....取值
                }
                return null;
            }
        });
    }
    public void query(){
        //查詢
        jdbcTemplate.query("sql", new RowMapper<Object>(){

            @Override
            public Object mapRow(ResultSet rs, int arg1) throws SQLException {
                rs.getString(0);
                //.....
                return null;
            }});
    }
}

上面就是spring操做數據庫了。此時就涉及到事務管理。若是使用spring事務管理尼。咱們能夠經過依賴注入@Transactional來使用提醒兩個注意點:框架

1.只有經過spring方式實例化纔有事務。經過new方式實例化將不包含事務
2.當調用的第一個方法有事務時,裏面調用的其餘方法也將包含在同一事務裏面,反之若是第一個方法沒有配置事務,方法內部平級調用方法(此方法配置了事務)。事務也將無效。socket

public class Test {
    @Transactional
    public void delData(){
        //有事務
        delTabA();
        //自己配置事務無效,事務類型與delData()一致
        delTabB();
    }
    public void delTabA(){
        
    }
    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public void delTabB(){
        
    }
}
class TestDemo{
    @Autowired
    private Test test;
    public void test() {
        //有事務
        test.delData();
        Test test2 = new Test();
        //無事務
        test2.delData();
    }
}

3.當方法中拋出異常時,若是聲明瞭拋出異常,事務是不回滾的。若是拋出異常時未檢查的。事務將會回滾。
若是須要回滾須要增長配置@Transactional(rollbackFor=Exception.class)指定異常,可同時配置多個異常ide

    import org.springframework.transaction.annotation.Transactional;

    public class Test2 {
        //出現異常將不會回滾
        @Transactional
        public void test ()throws Exception{
            throw new Exception();
        }
        //將會回滾
        @Transactional(rollbackFor=Exception.class)
        public void test2()throws Exception{
            throw new Exception();
        }
        //將會回滾
        @Transactional
        public void test3(){
            throw new RuntimeException("例外");
        }

    }

經過依賴注入能夠選着注入的事務類型 @Transactional(propagation=Propagation.REQUIRES_NEW)url

PROPAGATION_REQUIRED:支持當前事務,若是當前沒有事務,就新建一個事務。這是最多見的選擇。 
PROPAGATION_SUPPORTS:支持當前事務,若是當前沒有事務,就以非事務方式執行。 
PROPAGATION_MANDATORY:支持當前事務,若是當前沒有事務,就拋出異常。 
PROPAGATION_REQUIRES_NEW:新建事務,若是當前存在事務,把當前事務掛起。
PROPAGATION_NOT_SUPPORTED:以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。 
PROPAGATION_NEVER:以非事務方式執行,若是當前存在事務,則拋出異常。 
PROPAGATION_NESTED:支持當前事務,若是當前事務存在,則執行一個嵌套事務,若是當前沒有事務,就新建一個事務。

上面就是對單個方法進行事務控制。適合須要精細化處理的項目。但但部分項目不須要這麼精細。就能夠經過配置對某個包下方法進行IOC事務配置。spa

相關文章
相關標籤/搜索