1. 程式人生 > >JDBC和連線池使用步驟

JDBC和連線池使用步驟

          從實習到現在已經快一年啦,學習了很多也遺忘了很多,最近有空所以把以前的筆記整理一下放到部落格上。

JDBC:java database connectivity

          JDBC定義一套標準介面,即訪問資料庫的通用API,不同的資料庫廠商根據各自資料庫的特點去實現這些介面,實現介面、類:驅動:由資料庫廠商實現

         -JDBC是java應用程式和資料庫之間的通訊橋樑,是java應用程式訪問資料庫的通道

         -JDBC標準主要由一組介面組成,其好處是統一了各種資料庫訪問方式

        -JDBC介面的實現類稱為資料庫驅動,由各個資料庫廠商提供,使用JDBC必須匯入這個驅動!一定知道驅動是什麼!

connection只是介面,真正的實現是由資料庫廠商提供的驅動包

一、JDBC主要由一大堆介面組成:這些介面的實現類是由驅動提供的,Oracle驅動就是這些介面的實現類

JDBC使用步驟:

1、匯入JDBC驅動

         -使用Maven可以便捷地匯入資料庫驅動

1、註冊JDBC驅動  

        -引數:“驅動程式類名”   

         -Class.forname("驅動程式類名")

3、獲得Connection物件 

          - 需要三個引數:url,username,password  - 連線到資料庫

4、建立Statement(語句)物件

         -conn.getStatemnent()方法建立物件

         -用於執行SQL語句       -注意語句空格

         -execute(ddl)執行任何SQL,常用於執行DDL、DCL

         -executeUpdate(dml)執行DML語句,如:insert,update,delete

         -executeQuery(dql) 執行DQL語句,如:select

5處理執行結果:

         -execute(ddl)如果沒有異常則成功 boolean

         -executeUpdate(dml)返回數字,表示更新“行”數量,丟擲異常則失敗   int

         -executeQuery(dql)返回ResultSet(結果)物件,代表2維查詢結果,  ResultSet

         使用for遍歷處理,如果查詢失敗丟擲異常

6、關閉資料連線!!!關閉資料連線

         -conn.close();

、關於執行計劃

*.java源程式編譯成計算機可以看懂的*.class位元組碼;SQL語句翻譯成執行計劃才能執行

①、Statement主要用於執行靜態SQL語句,即內容固定不變的SQL語句;Statement每執行一次都要對傳入的SQL語句編譯一次,效率較差;沒有引數用Statement的話比preparedStatement快一點

②、PreparedStatement物件用於執行帶引數的預編譯執行計劃;可以重複使用執行計劃,提高DB效率,可以重用執行計劃,而且可以執行多次;可以避免注入攻擊。

 1、任何SQl都是先編譯“執行計劃”,再執行“執行計劃”

 2、資料庫為了優化效能,在SQL語句完全一樣的情況下,會重用執行計劃

         -執行計劃編譯較慢

         -重用執行計劃可以提高資料庫效能

3、資料庫只在SQL語句完全一樣的情況下,才會重用執行計劃

         -如果SQL語句中有一個字元的更改,也會執行不同的執行計劃

         -一個空格或者一個大小寫不同也會建立不同的執行計劃

使用步驟:

1、將帶引數的SQL傳送到資料庫建立執行計劃

2、替換執行計劃中的引數

3、執行執行計劃,得到結果

、資料庫連線池

資料庫連線池是管理併發訪問資料庫連線的理想解決方案

解決併發問題;資料庫的併發有限,限制連線數,避免資料庫崩潰;重用資料庫連線

Apahce DBCP

連線池是建立和管理連線的緩衝池技術,將連線準備好被任何需要他們的應用使用

DriverManager管理資料庫連線適合單執行緒情況,而在多執行緒併發情況下,為了能夠重用資料庫連線,同時控制併發連線總數,保護資料庫避免連線過載,一定要使用資料庫連線池

###使用DBCP連線池

資料庫連線池的開源實現非常多,DBCP是其中之一。

使用DBCP:1、匯入連線池jar

2、建立連線池物件

3、設定資料庫必須的連線引數

4、設定可選的連線池管理策略引數

5、從連線池中獲得活動的資料庫連線

6、使用連線範圍資料量

7、使用以後關閉資料庫連線,這個關閉不再是真的關閉連線,而是將使用過的連線歸還給連線池

連線管理工具類:

public class DBUtils {
    private static String driver;
    private static String url;
    private static String username;
    private static String password;
    private static int initSize;
    private static BasicDataSource ds; //連線池就一個

    static {
        ds = new BasicDataSource();
        Properties cfg = new Properties();
        //初始化靜態屬性
        //利用properties 讀取配置檔案
        //從配置檔案中查詢相應引數
        try {            //load天生有異常
            InputStream in = DBUtils.class.getClassLoader()
                    .getResourceAsStream("db.properties");
            cfg.load(in);

            driver = cfg.getProperty("jdbc.driver");
            url = cfg.getProperty("jdbc.url");
            username = cfg.getProperty("jdbc.username");
            password = cfg.getProperty("jdbc.pasaword");
            initSize = Integer.parseInt(cfg.getProperty("initSize"));
            in.close();
            //初始化連線池
            ds.setDriverClassName(driver);
            ds.setUrl(url);
            ds.setUsername(username);
            ds.setPassword(password);
            //設定連線池的管理策略引數
            ds.setInitialSize(initSize);

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public static Connection getConnection() {
        try {
            //getConnection()從連線池獲取重用的連線,如果連線池滿了,則等待
            //如果連線歸還,則獲取重用的連線; 連線池的執行緒阻塞方法
            Connection conn = ds.getConnection();
            return conn;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }

    public static void close(Connection conn) {
        try {
            //將用過的連線歸還到連線池
            if (conn != null) {
                conn.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void rollback(Connection conn) {
        try {
            //將用過的連線歸還到連線池
            if (conn != null) {
                conn.rollback();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

其配套引數設定檔案 db.propwerties:

#db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/checkaccount?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.username=root
jdbc.pasaword=
#paramter for BasicDataSourse
initSize=2

四、事務處理

資料庫提供了事務控制功能,支援ACID特性

JDBC提供了API,方便地呼叫資料庫的事務功能,其方法有:

        -Connection.getAutoCommit():獲得當前事務的提交方式,預設是true

         -Connection.setAutoCommit():設定事務的提交屬性,引數是true:自動提交;false:不自動提交,取消自動提交,後續手動提交

         -Connection.Commit():提交事務

         -Connection.rollback():回滾事務

標準呼叫事務的模板以及執行計劃使用步驟:

public static void dbTest() {
    Connection conn = null;
    try {
        conn = DBUtils.getConnection();
        conn.setAutoCommit(false);
        //業務處理 執行計劃使用步驟
        String sql = "insert into test_wcx values( ?,?,?)";
        // 1、將帶引數的SQL傳送到資料庫建立執行計劃
        PreparedStatement ps = conn.prepareStatement(sql);
        //2、替換執行計劃中的引數
        ps.setInt(1, 2);
        ps.setString(2, "weicx");
        ps.setString(3, "test");
        //3、執行執行計劃,得到結果
        int result = ps.executeUpdate();
        System.out.println(result);
        conn.commit();
    } catch (Exception e) {

        e.printStackTrace();

        DBUtils.rollback(conn);

    } finally {

        DBUtils.close(conn);

    }

}

事務Transaction:保證交易可靠

比如轉賬:扣除跟增加必須在一個事務中完成

事務特性ACID

原子性:表示不可再分單元,最小單元,事務必須都是原子工作單元;對於其資料修改,要麼全都執行,要不全都不執行

一致性:事務在完成時,必須使所有的資料都保持一致狀態

隔離性:由併發事務所做的修改必須與任何其他併發事務所做的隔離  不能被幹擾

永續性:事務完成之後,它對於系統的影響是永久性的

隔離有級別:

最低級別:修改一個可以看一個

現在學的是提交以後可以看,別人修改過程中可以看,看的是修改過程之前的資料:幻讀,是不真實的  

最高級別:就是別人修改過程中看都不能看

事務是資料庫的概念,JDBC支援事務,本質還是在資料庫中實現的

有在資料庫中沒有提交的事務  Java中操作會卡住(恩?卡住?)。