程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> java事務——本地事務,java事務

java事務——本地事務,java事務

編輯:JAVA綜合教程

java事務——本地事務,java事務


本地事務

事務類型

事務可以分為本地事務和分布式事務兩種類型。這兩種事務類型是根據訪問並更新的數據資源的多少來進行區分的。本地事務是在單個數據源上進行數據的訪問和更新,而分布式事務是跨越多個數據源來進行數據的訪問和更新。在這裡要說的事務是基於數據庫這種數據源的。

JDBC事務

在JAVA中,我們使用JDBC來連接數據庫,訪問和更新數據。那麼在JDBC中是如何實現事務的,事務是被誰來管理的?這個答案當然是數據庫,JDBC本身並沒有處理事務的能力,而是依賴於底層數據庫,底層數據庫來提供事務的服務。在很多資料上會提到,JDBC的事務是基於連接的,也就是那個Connection對象,這個連接的本質其實是連接到數據庫的一個Socket,與數據庫建立連接以後就可以向數據庫發送指令和數據,最終數據庫會根據接收到的指令和數據來進行增刪改查以及事務的處理。另外,事務是被限制在單個連接上的,這就好像我們去銀行的營業廳辦理業務,營業廳有多個窗口,我們只會在自己的窗口上與銀行工作人員進行溝通並處理自身的業務,而不能跨窗口,告訴別的窗口的工作人員把那哥們的錢轉到自己卡上,這事也就只能想想。

 

數據庫事務例子

 

下面先看一個MYSQL數據庫事務的例子:

 

1、創建表

創建用戶表

CREATE TABLE USERS
(
    USER_ID INT NOT NULL AUTO_INCREMENT  COMMENT '自增主鍵',
    USER_NAME VARCHAR(25) NOT NULL  COMMENT '用戶名',
    PASSWORD  VARCHAR(25) NOT NULL COMMENT '密碼',
    GENDER    VARCHAR(1)  COMMENT '性別',
    PHONE_NO VARCHAR(11) NOT NULL COMMENT '手機號',
        CREATE_TIME DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT '創建時間',
    PRIMARY KEY (USER_ID)
)
COMMENT = '用戶表';

創建用戶和角色的關聯關系表

CREATE TABLE USER_ROLE_RELATION
(
    REL_ID INT NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
    USER_ID INT NOT NULL COMMENT '用戶ID',
    ROLE_ID INT NOT NULL COMMENT '角色ID',
    PRIMARY KEY (REL_ID)
)
COMMENT = '用戶和角色對應關系表'

2、創建存儲過程,在存儲過程中使用事務

BEGIN
    #聲明一個標志位,默認為0
    DECLARE T_ERROR INTEGER DEFAULT 0;
    #如果事務執行過程中出現異常,那麼把標志位設置為1
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET T_ERROR = 1;  
    #開始事務
    START TRANSACTION; 
INSERT INTO USERS (USER_NAME, PASSWORD, GENDER, PHONE_NO) VALUES ('zhangsan', '123456', '男', '11111111111'); INSERT INTO USER_ROLE_RELATION (USER_ID, ROLE_ID) VALUES ('333', '1'); #如果執行成功,直接提交,否則回滾 IF T_ERROR = 0 THEN COMMIT; ELSE   ROLLBACK; END IF; END

3、執行存儲過程

存儲過程執行成功以後,數據庫的這兩個表中會分別出現一條記錄。然後把

INSERT INTO USER_ROLE_RELATION (USER_ID, ROLE_ID) VALUES ('333', '1');

這個語句改為:

#這條INSERT語句違反了非空約束,會拋出異常
INSERT INTO USER_ROLE_RELATION (USER_ID, ROLE_ID) VALUES (NULL, '1');

重新保存並執行存儲過程,結果是兩個表中都沒有新增記錄。兩條SQL語句要麼同時成功,要麼同時失敗。

 

JDBC事務例子

 

JDBC中如果需要手動提交事務的話,需要用到Connection對象中的三個方法:

 

//設置是否自動提交
setAutoCommit()
//提交
commit()
//回滾
rollback()

 

在JDBC中事務的提交方式默認是自動提交的,手動提交的事務的話需要更改默認設置:

 

Connection.setAutoCommit(false)

 

下面這個例子是假設新增一個用戶並給用戶賦默認權限,那麼需要同時向兩張表中分別插入一條記錄,把新增用戶和賦權限看做是一個執行單元,放在一個事務中。

package person.lb.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


public class TestJDBCTransAction {

    static {
        try {
            //加載驅動類
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } 
    }
    
    public static void main(String[] args) {
        //執行事務
        executeTransaction();
    }

    private static void executeTransaction() {
        Connection conn = null;
        Statement st1 = null;
        Statement st2 = null;
        ResultSet rs = null;
        try {
            //獲取數據庫連接
            conn = (Connection) DriverManager.getConnection(
                    "jdbc:mysql://192.168.0.105:3306/TEST", 
                    "root", 
                    "root");
            conn.setAutoCommit(false);
            
            st1 = (Statement) conn.createStatement();
            st2 = (Statement) conn.createStatement();
            //插入用戶信息
            st1.execute("INSERT INTO USERS (USER_NAME, PASSWORD, GENDER, PHONE_NO) "
                      + "VALUES ('zhangsan', '123456', '男', '11111111111')"
                      , Statement.RETURN_GENERATED_KEYS);
            //獲取增長列的新值
            rs = st1.getGeneratedKeys();
            String userID = "";
            if(rs.next()) {
                userID = rs.getString(1);
            }
            //插入用戶和角色關聯數據
            st2.execute("INSERT INTO USER_ROLE_RELATION (USER_ID, ROLE_ID) VALUES (" +userID +", '1')");
            conn.commit();
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                conn.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            try {
                if(rs != null) {
                    rs.close();
                }
                if(st1 != null) {
                    st1.close();
                }
                if(st2 != null) {
                    st2.close();
                }
                if(conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

程序執行結果如下:

USERS表

USER_ROLE_RELATION表

 

 

到這裡,JAVA的本地事務算是寫完了。

 

 

 

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved