Java 數據庫連接——JDBC

JDBC 全程是 Java Database Connectivity,是一種用於執行 SQL 語句的 Java API,它由一組用 Java 編寫的類和接口組成,屬於 Java EE 的一部分。


圖:JDBC 處於數據庫驅動和應用程序之間,爲多種關係型數據庫提供統一的訪問

JDBC 使用分爲 7 步:
0. 導入 JDBC 的驅動程序,在 java project 的 built-in path 中加入 mysql-connector-5.1.8.jar
1. 註冊 JDBC 驅動程序,最常使用 Class.forName(“…”)
2. 創建 Connection 對象,依據數據庫的 URL,調用 DriverManager.getConnection( ) 方法
3. 創建 Statement 對象,connection.createStatement()
4. 執行 SQL 操作,返回 ResultSet
5. 對 ResultSet 進行處理
6. 清理環境,釋放資源


圖:本博客使用的 Students 表是這樣的。
我被一個小 BUG 折騰了一個小時:mysql 安裝在我的虛擬機的 linux裏面,我的 java 代碼在 windows 的 eclipse 裏面。我的步驟 2,創建 connection 部分一直失敗。最後終於發現,我的linux 裏面的 mysql 不允許遠程訪問。。。最後通過百度,更改 mysql 配置解決了。


show me the code

Statement

package jdbc_test;

import java.sql.*;

public class mysql_jdbc_test
{
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";               // JDBC 驅動名稱
    static final String DB_URL = "jdbc:mysql://192.168.1.108:3306/EXAMPLE?"; // URL,IP地址:mysql端口/數據庫名
    static final String USER = "...";
    static final String PASSWORD = "...";

    public static void main(String[] args)
    {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        try
        {
            Class.forName(JDBC_DRIVER);                                        // 步驟 1
            connection = DriverManager.getConnection(DB_URL, USER, PASSWORD);  // 步驟 2
            statement = connection.createStatement();                          // 步驟 3
            String sql = "SELECT id, name, age FROM Students";
            resultSet = statement.executeQuery(sql);  // 步驟 4

            while (resultSet.next())                  // 步驟 5
            {
                int id = resultSet.getInt("id");
                int age = resultSet.getInt("age");
                String name = resultSet.getString("name");

                System.out.print("ID: " + id);
                System.out.print(", Age: " + age);
                System.out.print(", Name: " + name);
                System.out.println();
            }

        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally  // 步驟 6
        {
            try
            {
                if (resultSet != null)
                {
                    resultSet.close();
                    resultSet = null;
                }
                if (statement != null)
                {
                    statement.close();
                    statement = null;
                }
                if (connection != null)
                {
                    connection.close();
                    connection = null;
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

PreparedStatement

PreparedStatement 比單純的 Statement 更好用,也用的更多,前者接口是後者接口的擴展。有利於執行多次使用的 SQL 語句,節省 String sql 的個數,可以靈活指定 SQL 語句中的變量。SQL語句中,用 ’ ? ’ 代表變量,佔個位置。然後使用 setInt( ),setString( ) 設置參數。

PreparedStatement 和 Statement 兩者相差的“prepared”,從代碼層面可以看出來:connection 返回 PreparedStatement 對象的方法需要參數“帶?的sql 語句”,connection 返回 Statement 對象的方法不需要參數。

package jdbc_test;

import java.sql.*;

public class PreparedStmt
{
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://192.168.1.108:3306/EXAMPLE";
    static final String USER = "...";
    static final String PASSWORD = "...";

    public static void main(String[] args)
    {
        Connection connection = null;
        PreparedStatement pStatement = null;
        ResultSet rSet = null;
        try
        {
            Class.forName(JDBC_DRIVER);
            connection = DriverManager.getConnection(DB_URL, USER, PASSWORD);

            String sql = "UPDATE Students set age = ? WHERE id = ?";
            pStatement = connection.prepareStatement(sql);
            pStatement.setInt(1, 20);
            pStatement.setInt(2, 1);

            sql = "SELECT id, name, age FROM Students";
            rSet = pStatement.executeQuery(sql);

            while (rSet.next())
            {
                int id = rSet.getInt("id");
                int age = rSet.getInt("age");
                String name = rSet.getString("name");

                System.out.print("ID: " + id);
                System.out.print(", Age: " + age);
                System.out.print(", Name: " + name);
                System.out.println();
            }
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if (rSet != null)
                {
                    rSet.close();
                    rSet = null;
                }
                if (pStatement != null)
                {
                    pStatement.close();
                    pStatement = null;
                }
                if (connection != null)
                {
                    connection.close();
                    connection = null;
                }
            }
            catch (Exception e2)
            {
                e2.printStackTrace();
            }
        }
    }
}

進階

DML:Database Manipulate Language,數據庫操縱語言,就是 update, insert, delete。JDBC 中用 connection.executeUpdate( ) 一個方法統一了三種操縱方式。

CallableStatement:對存儲過程進行調用。參數類型有三種:IN, OUT, INOUT。
IN       :setXXX( … )
OUT    :getXXX( … )
INOUT:同時提供輸入和輸出參數,setXXX( … ) + getXXX( .. )

ResultSet:由查詢語句生成,表示數據庫查詢結果的數據表。ResultSet默認不可更新,僅有一個向前移動的指針,該指針初始位置在第一行之前。如果不默認的話,可以有很多設置,比如:遊標指針可以前後移動,結果集是否可以即時更新,是否可以更新。是的注意的是:JDBC 提供了這些接口,但是數據庫廠商(MySql,Oracle 等)不一定都去實現。
創建 ResultSet 的參數設置細節,實驗樓網站課程

Transaction:運用事物處理。默認情況下,JDBC 連接是在自動提交模式下的。一個 Transaction 把一個SQL 或者多個 SQL 作爲一個邏輯單元,保證這個邏輯單元裏面的所有 SQL 語句在同一時間共同執行。要麼一起成功,要麼一起失敗。如果失敗,則整個事物回滾。好處是:提高程序運行的性能,保持業務流程的完整性,使用分佈式業務管理方式。
connection.setAutoCommit(false);
connection.commit( );
connection.rollback(); ( catch 語句裏面,出現異常,撤銷事務 )

Batch:批處理。把相關的 SQL 語句組合成一個批處理和一個調用數據庫提交。當一次發送多個 SQL 語句到數據庫,可以減少通信開銷。
addBatch( … )
executeBatch( … )
commit( )
批處理和事務代碼樣例

RowSet:默認是一個可滾動,可更新,可序列化的結果集。RowSet 的離線操作能有效的利用計算機的內存,減輕數據庫服務器的負擔。數據操作在內存中操作,然後批量提交到數據源,靈活性和性能都得到了很大的提高。RowSet 從 ResultSet 繼承,支持斷開結果集,支持 JavaBean

DataSource: DriverManager 的代替,在內部通過一個的機制來複用數據庫連接,這樣大大的減少了創建數據庫連接的次數,提高了系統性能。連接池實現,分佈式實現,DataSource 屬性可以動態改變

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