關於jdbc批處理&事務概念與性質

提綱:
1. JDBC使用快速回顧
2. 批處理
3. 事務

複習

  1. 怎樣註冊驅動
                Class.forName("com.sql.jdbc.Driver");

2.怎樣獲取連接對象

             DriverManager.getConnection(url,name,password);
            url作用:通過url可以知道具體加載哪一個驅動

            mysql的url可以簡寫:jdbc:myql:///mydb
  1. 怎樣獲取可以操作sql語句的對象
                Statement st=conn.createStatement();      

                st.executeQuery();
                st.executeUpdate();                
                st.execute();

                PreparedStatement pst=conn.prepareStatement(sql);   //佔位符是?
                setXXX()

                executeQuery();
                pst.executeUpdate();

4.執行查詢語句後,可以得到ResultSet

                ResultSet  rs=st.executeQuery(sql);

                rs.next();

                getObject()
                getInt();

5.關閉資源

                rs.close();
                st.close();
                conn.close();     

關於多數據處理.

批處理

    批處理應用:一次可以執行多條sql語句

    批處理有兩種方式
            1.Statement
                         addBatch(String sql)  //將多條sql語句回到批處理中
                         cleaarBatch();        //清空所有的sql
                         executetBatch();      //執行一批sql     
            2.PreparedStatement
                         addBatch();           //添加SQL語句回到批處理
                         executeBaatch();      //批量執行sql

Statement與PreparedStatement區別

1.Statement適合執行不同的sql語句 PreparedStatement適合執行相同的sql語句
2.Statement在執行時比PreParedStatement的效率低1

看兩個demo吧

我先把jdbc封裝到一個utils裏面

package cn.lawfree.JDBC.util;

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

public class JdbcUtil {

    private static String DRIVER;
    private static String URL;
    private static String USERNAME;
    private static String PASSWORD;

    // private static final ThreadLocal<Connection> tl = new
    // ThreadLocal<Connection>();

    static {
        // 獲取連接數據
        ResourceBundle bundle = ResourceBundle.getBundle("db");
        DRIVER = bundle.getString("driver");
        URL = bundle.getString("url");
        USERNAME = bundle.getString("username");
        PASSWORD = bundle.getString("pwd");

    }
    static {
        try {
            Class.forName(DRIVER);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("加載驅動加載驅動");
        }
    }


    // 創建一個可以去Connection對象的方法
    public static Connection getConnection() {
        Connection conn = null;

        try {
            conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);

        } catch (SQLException e) {
            // throw new RuntimeException("獲取連接失敗");
            e.printStackTrace();
        }
        return conn;
    }

    // 關閉方法Connection方法
    public static void closeConnection(Connection conn) throws SQLException {
        if (conn != null) {
            conn.close();
        }
    }

    // 關閉Statement方法
    public static void closeStatement(Statement st) throws SQLException {
        if (st != null) {
            st.close();
        }
    }

    // 關閉ResultSet方法
    public static void closeResultSet(ResultSet rs) throws SQLException {
        if (rs != null) {
            rs.close();
        }
    }
}
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import cn.lawfree.JDBC.util.JdbcUtil;

//statement的批處理
public class Demo1 {
    public static void main(String[] args) throws SQLException {

        String sql0 = "use t_testpatch";
        String sql1 = "create table user(id int,name varchar(20),sex varchar(10),age int  )";
        String sql2 = "insert into user values(1,'tom','male','20')";
        String sql3 = "insert into user values(2,'fox','male','30')";
        String sql4 = "update user set age=40 where id=1";

        // 1.獲取Connection對象
        Connection conn = JdbcUtil.getConnection();
        // 2.獲取Statement對象
        Statement st = conn.createStatement();

        // 3.將sql語句添加到stst.addBatch(sql0);
        st.addBatch(sql1);
        st.addBatch(sql2);
        st.addBatch(sql3);
        st.addBatch(sql4);

        // 4.批處理
        st.executeBatch();

        // 5.關閉資源
        st.close();
        conn.close();
    }
}
package cn.lawfree.JDBC.batch;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import cn.lawfree.JDBC.util.JdbcUtil;

//PreparedStatement執行批處理 
public class demo2 {
    public static void main(String[] args) throws SQLException {
        Connection conn = JdbcUtil.getConnection();
        String sql = "insert into user values(?,?,?,?)";
        PreparedStatement pst = conn.prepareStatement(sql);

        for (int i = 1; i < 10; i++) {
            pst.setInt(1, i);
            pst.setString(2, "name" + i);
            pst.setString(3, "male");
            pst.setInt(4, 20 + (int) (Math.random() * 10));

            // 添加到批處理
            pst.addBatch();

        }

        // 執行
        pst.executeBatch();

        pst.close();
        conn.close();
        conn.close();
    }
}

事務

通俗地講:事務是指一組操作,組成這組操作的功能,要不全部成功,要不全部不成功
關於事務
1.數據庫本意識提供事務.
2.jdbc提供對事務的處理.

1.數據庫中事務處理

            mysql事務是自動提交的.------默認情況,事務自動提交,一條sql語句是一個單獨事務
            oracle事務是手動提交.   commit

            start transaction ------開啓事務
            rollback          ------回滾
            commit            ------提交事務      

mysql可以設置提交方式嗎?
show variables like ‘%commit’; 查看提交方式
set autocomit=off/on; 關閉自動提交

演示 start transaction rollback commit使用

                 create table acount(
                      id int,
                      name varchar(10),
                      money int
                 )       

                 insert into account values(1,'aaa',1000);      
                 insert into account values(2,'bbb',1000);          
                 insert into account values(3,'ccc',1000);           

                 aaa--匯款給-->bbb  500元
                 update acount set money=money-500 where name='aaa';  從aaa前去500.
                 update acount set money=money+500 where name='bbb';  給bbb加上500.

事務處理操作
1.start transcation.
2.

                 update acount set money=money-500 where name='aaa';  從aaa前去500.
                 update acount set money=money+500 where name='bbbb';  給bbb加上500.

3.發現數據有問題–>rollback;
4. commit

2.jdbc事務處理

在Connection中提供

                             setAutoCommit(boolean f);  //-----設置事務的提交方式
                             rollback();                //-----事務回滾 
                             commit();                  //-----事務提交

這三個方法是jdbc中事務的三個方法
Savepoint 回滾點
con.setSavepoint(); 獲取(設置回滾點)

                             rollback(Savepoint) ;//這樣使用 

還是來看一個demo

package cn.lawfree.JDBC.transaction;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

//這是轉賬操作的底層實現
//包含兩個方法,存錢和取錢方法
public class AccountDao {

    // 存儲
    public void save(double money, String name, Connection conn)
            throws SQLException {
        String sql = "update account set money=money+? where name=? ";

        PreparedStatement pst = conn.prepareStatement(sql);

        pst.setDouble(1, money);
        pst.setString(2, name);

        int row = pst.executeUpdate();
        if (row == 0) {
            throw new RuntimeException("存款失敗");
        }

        pst.close();

    }

    // 取錢
    public void get(double money, String name, Connection conn)
            throws SQLException {
        String sql = "update account set money=money-? where name=?";

        PreparedStatement pst = conn.prepareStatement(sql);

        pst.setDouble(1, money);
        pst.setString(2, name);

        int row = pst.executeUpdate();
        if (row == 0) {
            throw new RuntimeException("存款失敗");
        }
        pst.close();

    }
}
package cn.lawfree.JDBC.transaction;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Savepoint;

import cn.itcast.lawfree.util.JdbcUtil;

//這是轉賬支付的service操作,主要用於實現事務邏輯
//我們給它添加一個回滾的邏輯
public class AccountService {
    public void hk() {

        AccountDao dao = new AccountDao();
        Connection conn = JdbcUtil.getConnection();
        // 開啓事務 ------setAutoCommit(false);

        Savepoint point = null;

        try {
            conn.setAutoCommit(false);
            // 1.從a賬戶取錢500

            dao.get(500, "aaa", conn);

            // 設置一個回滾點
            point = conn.setSavepoint();

            // 2.向賬戶存500;
            dao.save(500, "bbb", conn);
        } catch (SQLException e) {
            // 回滾
            // rollback
            try {
                conn.rollback(point);
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {

            try {
                // commit
                conn.commit();
                // 關閉conn
                JdbcUtil.closeConnection(conn);
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

    }
}

事務的特性(ACID)

1.原子性(Atomicity)
原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生
2.一致性(Consistency)
事務前後數據的完整性必須一致
3.隔離性(Isolation)
事務的隔離性是指多個用戶併發訪問數據庫時,一個用戶的事務不能被其他用戶的事務所幹擾,多個併發事務之間的數據要相互隔離
4.持久性(Durability)
持久性是指一個事務一旦被提交.它對數據庫中數據的改變是永久性的,接下來即使數據庫發生故障也不應該對其有任何影響

*重點介紹事務的隔離性*
如果不考慮事務的隔離性會引發的問題
1. 髒讀 一個事務讀取到另一個事務的未提交數據

                            A 轉賬給B 100,未提交
                            B 查詢賬戶多了100
                            A 回滾
                            B 查詢賬戶那100不見了

2.不可重複讀 兩次讀取的數據不一致(強調的是update操作,數據的總條數不變

                            將隔離級別設置成  Read committed.查看是否可以解決髒讀問題

演示不可重複讀:

                            A 轉賬 給B 100,未提交
                            B 查詢 金額沒變(級別是: Read committed  避免了髒讀)
                            A 查詢,發現金額多了100

                            兩次讀取到的數據不一致,出現了不可重複讀.
  1. 虛讀(幻讀) 兩次讀取的數據不一致(強調的是insert操作,數據的總條數變化)

事務的隔離級別

數據庫中一共有四種隔離級別
1.Serializable:可避免髒讀 不可重複讀 虛讀情況的發生.(串行化)
2.Repeatable read:可避免髒讀 不可重複讀情況發生(輸入一個commit即可得到最新數據) .(可重複讀)不可避免虛讀
3.Read committed:可避免髒讀情況發生(讀已提交)
4.Read uncommitted:最低級別,以上情況均無法保證(讀未提交)

mysql默認的隔離級別是什麼?怎麼設置隔離級別?

mysql默認隔離級別是Repeatable read 級別

                    select @@tx_isolation   查詢當起事務隔離級別 

                    set session transaction isolation level  設置事務隔離級別

                    set session transaction isolation level Read uncommitted;

                    serializable會出現鎖表情況      

                    安全性越高的,性能越低    

下面我們用mysql具體來看看不同的事務隔離級別會發生什麼.
1. 準備一個表account,用兩個Mysql打開打開,就像這樣:
2. 我們已經知道Mysql默認事務隔離級別是Repeatable read,我們先來看看能不能避免髒讀和不可重複讀:
3. 由於csdn傳圖片卡到爆?以後有空再弄……

JDBC設置事務的隔離級別

        在connection接口中提供
        setTransactionIsolation(int level)用來設置事務的隔離級別

        四個級別字段          

小結:
1.Statementment與PreparedStatement執行批處理的特點
Statement適合執行多條不同的sql
PreparedStatement適合執行相同的sql
2.事務
一組操作,要麼全部成功,要麼全不成功
3.mysql中的事務管理
1.start transcation rollback commit.
2.mysql中的事務默認是
autocommit=on 可手動修改
autocommit=off
oracle數據庫它的事務必須手動提交
4.jdbc管理事務

                     Connection下的
                              1.setAutoCommit(boolean flag)
                              2.rollback
                              3.commit
                              4.Savepoint回滾點

5.事務特性 (重點)

                      ACID
                      原子性    一致性    gelixing    持久性                                                                                      

6.隔離性
不考慮隔離性會發生什麼問題?

                              1.髒讀     2.不可重複讀    3虛讀(幻讀)

7.隔離級別

                      1.Serializable:可避免髒讀 不可重複讀 虛讀情況的發生.(串行化)
                      2.Repeatable read:可避免髒讀 不可重複讀情況發生(輸入一個commit即可得到最新數據) .(可重複讀)不可避免虛讀    
                      3.Read committed:可避免髒讀情況發生(讀已提交)
                      4.Read uncommitted:最低級別,以上情況均無法保證(讀未提交)    

8.jdbc怎樣設置事務的隔離級別

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