中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring學習筆記事務(一)

發布時間:2020-07-28 12:59:14 來源:網絡 閱讀:383 作者:luchunli1985 欄目:數據庫

魯春利的工作筆記,好記性不如爛筆頭



事務是一系列操作組成的工作單元,是不可分割的,即要么所有操作都做,要么所有操作都不做,這就是事務。
事務必需滿足ACID(原子性、一致性、隔離性和持久性)特性,缺一不可:
    原子性(Atomicity):即事務是不可分割的最小工作單元,事務內的操作要么全做,要么全不做;
    一致性(Consistency):在事務執行前數據庫的數據處于正確的狀態,而事務執行完成后數據庫的數據還是處于正確的狀態;
    隔離性(Isolation):并發事務執行之間無影響,在一個事務內部的操作對其他事務不會產生影響;
    持久性(Durability):事務一旦執行成功,它對數據庫的數據的改變必須是永久的。

在實際項目開發中數據庫操作一般都是并發執行的,即有多個事務并發執行,并發執行就可能遇到問題,目前常見的問題如下:
    更新丟失:兩個事務同時更新一行數據,最后一個事務的更新會覆蓋掉第一個事務的更新,從而導致第一個事務更新的數據丟失,這是由于沒有加鎖造成的;
    臟讀:一個事務看到了另一個事務未提交的更新數據;
    不可重復讀:在同一事務中,多次讀取同一數據卻返回不同的結果;也就是有其他事務更改了這些數據;
    幻讀:一個事務在執行過程中讀取到了另一個事務已提交的插入數據;即在第一個事務開始時讀取到一批數據,但此后另一個事務又插入了新數據并提交,此時第一個事務又讀取這批數據但發現多了一條,即好像發生幻覺一樣。


為了解決這些并發問題,需要通過數據庫隔離級別來解決,在標準SQL規范中定義了四種隔離級別:
    讀未提交(Read Uncommitted):最低隔離級別,一個事務能讀取到別的事務未提交的更新數據,很不安全,可能出現更新丟失、臟讀、不可重復讀、幻讀;
    讀已提交(Read Committed):一個事務能讀取到別的事務提交的更新數據,不能看到未提交的更新數據,不可能可能出現丟失更新、臟讀,但可能出現不可重復讀、幻讀;
    可重復讀(Repeatable Read):保證同一事務中先后執行的多次查詢將返回同一結果,不受其他事務影響,可能可能出現丟失更新、臟讀、不可重復讀,但可能出現幻讀;
    序列化(Serializable):最高隔離級別,不允許事務并發執行,而必須串行化執行,最安全,不可能出現更新、臟讀、不可重復讀、幻讀。

數據庫事務類型有本地事務和分布式事務:
    地事務:普通事務,單臺數據庫操作的ACID;
    分布式事務:即跨越多臺同類或異類數據庫的事務。
Java事務類型有JDBC事務和JTA事務:
    JDBC事務:通過Connection對象的控制來管理事務;
    JTA事務:JTA指Java事務API(Java Transaction API),是Java EE數據庫事務規范, JTA只提供了事務管理接口,由應用程序服務器廠商(如WebSphere Application Server)提供實現,JTA事務比JDBC更強大,支持分布式事務。


在JDBC模式下,由程序員獲取數據庫連接、執行數據操作并控制事務,如:

package com.invicme.apps.tx.jdbc;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

/**
 * 
 * @author lucl
 * 
 * JDBC數據庫連接的工具類
 *
 */
public class DbHelper {
    /**
     * 
     */
    private static String driver = null;
    private static String url = null;
    private static String username = null;
    private static String password = null;
    static {
        // 該properties配置文件與工具類位于同一目錄下
        InputStream in = DbHelper.class.getResourceAsStream("jdbc.properties");
        Properties props = new Properties();
        try {
            props.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
        driver = props.getProperty("jdbc.driver");
        url = props.getProperty("jdbc.url");
        username = props.getProperty("jdbc.username");
        password = props.getProperty("jdbc.password");
    }
    
    /**
     * 獲取數據庫連接
     * 
     * @return
     */
    public Connection getCon () {
        Connection con = null;
        try {
            Class.forName(driver).newInstance();     // MYSQL驅動
            con = DriverManager.getConnection(url, username, password); // 鏈接本地MYSQL
        } catch (Exception e) {
            con = null;
            e.printStackTrace();
        }
        return con;
    }
    
    /**
     * 關閉數據庫連接
     * 
     * @param con
     * @throws SQLException
     */
    public void closeCon (Connection con) throws SQLException {
        if (null != con) {
            con.close();
        }
    }
    
}


單元測試類

package com.test.apps.spring.tx;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.log4j.Logger;
import org.junit.Test;

import com.invicme.apps.tx.jdbc.DbHelper;

/**
 * 
 * @author lucl
 *
 */
public class TestJdbcTransaction {
    // 
    private static final Logger logger = Logger.getLogger(TestJdbcTransaction.class);
    
    @Test
    public void testJdbcTransaction () {
        DbHelper dbHelper = new DbHelper();
        Connection con = dbHelper.getCon();
        
        try {
            DatabaseMetaData metaData = con.getMetaData();
            /**
             * 數據庫基本信息
             */
            // MySQL
            String databaseProductName = metaData.getDatabaseProductName();
            // 5.6.17-log
            String databaseProductVersion = metaData.getDatabaseProductVersion();
            // 5
            int databaseMajorVersion = metaData.getDatabaseMajorVersion();
            // 6
            int databaseMinorVersion = metaData.getDatabaseMinorVersion();
            
            // MySQL 5.6.17-log
            logger.info(databaseProductName + " " + databaseProductVersion);
            // 5.6
            logger.info(databaseMajorVersion + "." + databaseMinorVersion);
            
            int defaultTransactionIsolation = metaData.getDefaultTransactionIsolation();
            // 事務隔離級別:2
            logger.info(defaultTransactionIsolation);
            boolean supportsTransactions = metaData.supportsTransactions();
            // 是否支持事務:true
            logger.info(supportsTransactions);
            
            String driverName = metaData.getDriverName();
            String driverVersion = metaData.getDriverVersion();
            int driverMajorVersion = metaData.getDriverMajorVersion();
            int driverMinorVersion = metaData.getDriverMinorVersion();
            // MySQL Connector Java
            logger.info(driverName);
            // mysql-connector-java-5.1.38 ( Revision: fe541c166cec739c74cc727c5da96c1028b4834a )
            logger.info(driverVersion);
            // 5.1
            logger.info(driverMajorVersion + "." + driverMinorVersion);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        
        try {
            // 關閉自動提交
            con.setAutoCommit(false);
            
            Statement statement = con.createStatement();
            
            statement.executeUpdate("update user set name='zhangsan' where name='lisi' ");
            
            // 事務提交
            con.commit();
        } catch (SQLException e) {
            e.printStackTrace();
            // 事務回滾
            try {
                con.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            try {
                dbHelper.closeCon(con);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

    說明:

    在JDBC2.0中,事務只能進行commit或rollback;而JDBC3.0引入了保存點特性,即允許將事務分割為多個階段。

Savepoint savepoint = con.setSavepoint("svpt");
// ......
con.rollback(savepoint);


    Spring簡化了這個過程,提供了兩種事務控制方式,即:聲明式事務(注解方式和XML配置方式)和編程式事務。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

德清县| 正镶白旗| 林西县| 旺苍县| 维西| 桑日县| 鹤庆县| 博白县| 南丹县| 东平县| 西贡区| 北海市| 乌拉特前旗| 尚义县| 耿马| 大连市| 嘉禾县| 曲阳县| 招远市| 北川| 杭州市| 永顺县| 丘北县| 沁水县| 七台河市| 安化县| 丹凤县| 托克托县| 苍南县| 周宁县| 繁昌县| 远安县| 新沂市| 密云县| 油尖旺区| 西畴县| 阿坝县| 商丘市| 塔河县| 峨山| 梅河口市|