JDBC 數據庫連接技術簡介

JDBC 基本介紹



1. JDBC 概念

  JDBC(Java DataBase Connectivity,Java數據庫連接),是一種用於執行 SQL 語句的 Java API ,可以爲多種關係數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。JDBC 提供了一種基準,據此可以構建更高級的工具和接口,使數據庫開發人員能夠編寫數據庫應用程序,同時,JDBC也是個商標名。

JDBC 百度百科

概念解釋:

  • 定義了一套操作所有關係型數據庫的規則(接口)。
  • 不同的 JDBC 實現類由不同的廠商實現(數據庫驅動),提供驅動數據庫的 jar 包。
  • 我們可以使用這套 JDBC 編程,正真執行的代碼是驅動 jar 包中的實現類。


2. 快速入門

2.1 建表

首先在MySQL數據庫中準備一個表供後續的所有操作。

-- 創建用戶賬單表
create table account(
  id INT PRIMARY KEY AUTO_INCREMENT,
  a_name VARCHAR(30),
  a_money DOUBLE
);
-- 添加張三、李四的賬戶
insert into account(id,a_name,a_money) values
(1,"張三",1000),
(2,"李四",1000);

2.2 代碼展示

  需要提前導入連接數據庫的包,如果沒有,參考這篇教程 MySQL驅動下載

  我這裏用的是 MySQL8.0.17 版本,根據自己數據庫的安裝版本下載對應的驅動。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/**
 * JDBC快速入門
 * 實現,轉賬操作
 */
public class JdbcDemo {
    public static void main(String[] args) throws Exception{
        //1. 導入jar包
        //2. 註冊驅動:5.0版本後可以省略這一步書寫
        Class.forName("com.mysql.cj.jdbc.Driver");
        //3. 獲取數據庫連接對象:
        //若連接本地默認3306端口數據庫可以簡寫爲jdbc:mysql:///數據庫名?serverTimezone=UTC
        Connection conn =  DriverManager.getConnection("jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC","root","root");
        //4. 定義sql
        String sql1 = "update account set a_money = 500 where id = 1";
        String sql2 = "update account set a_money = 1500 where id = 1";
        //5. 獲取sql的對象 Statement
        Statement stmt = conn.createStatement();
        //6. 執行sql
        int count = stmt.executeUpdate(sql1);
        int count2 = stmt.executeUpdate(sql2);
        //7. 查看處理結果
        System.out.println(count);
        System.out.println(count2);
        //8. 釋放資源
        stmt.close();
        conn.close();
    }
}

注意:

  • mysql 5.0 註冊驅動:com.mysql.jdbc.Driver
  • mysql 5.0 連接數據庫:jdbc:mysql://localhost:3306/demo_test
  • mysql 8.0 註冊驅動:com.mysql.cj.jdbc.Driver
  • mysql 8.0 連接數據庫:jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC


3. JDBC 中各個對象

Java.sql 的 API 介紹

  這裏簡單介紹幾個常用管理對象,具體參照 API 中的介紹。

對象 功能 API介紹
DriverManager 與驅動程序建立連接 DriverManager 的API介紹
Connection 提供創建語句以及管理連接及其屬性的方法 Connection 的API介紹
Statement 執行sql的對象,用於發送基本的SQL語句。 Statement 的API介紹
PreparedStatement 執行sql對象,用於發送準備好的語句或基本的SQL語句 PreparedStatement 的API介紹
ResultSet 檢索和更新查詢結果 ResultSet 的API介紹


3.1 DriverManager

  用於管理一組JDBC驅動程序的基本服務。

方法 描述
static Connection getConnection​(String url, String user, String password) 嘗試建立到給定數據庫URL的連接。

參數解釋:

  • url:指定連接的路徑:jdbc:mysql://ip地址(域名):端口號/數據庫名稱
    • 如果連接的是本機 MySQL 服務器,並且 MySQL 服務器默認端口是 3306,則 url 可以簡寫爲:jdbc:mysql:///數據庫名稱 。
  • user:數據庫連接用戶名
  • password:數據庫連接密碼

代碼應用片段:

Connection conn =  DriverManager.getConnection("jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC","root","root");

3.2 Connection

  與特定數據庫的連接(會話)。執行SQL語句,並在連接的上下文中返回結果。

方法 描述
Statement createStatement() 創建一個Statement對象,用於將SQL語句發送到數據庫。
PreparedStatement prepareStatement​(String sql) 創建一個PreparedStatement對象,用於將參數化的SQL語句發送到數據庫
void setAutoCommit​(boolean autoCommit) 將此連接的自動提交模式設置爲給定狀態。
void commit() 使自上一次提交/回滾以來的所有更改永久生效,並釋放此Connection對象當前持有的所有數據庫鎖。
void rollback() 撤消在當前事務中進行的所有更改,並釋放此Connection對象當前持有的所有數據庫鎖。

代碼應用片段:

Statement stmt = conn.createStatement();
int count = stmt.executeUpdate(sql);

3.3 Statement

  用於執行靜態SQL語句並返回其產生的結果的對象。

方法 描述
boolean execute​(String sql) 執行任意給定的SQL語句,該語句可能返回多個結果。
int executeUpdate​(String sql) 執行DML(insert、update、delete)返回改變行數,或者執行DDL(create、alter、drop)不返回任何內容。
ResultSet executeQuery​(String sql) 執行給定的SQL語句,該語句返回一個 ResultSet對象。

代碼應用片段:

Statement stmt = null;
int count = stmt.executeUpdate(sql);
int count = stmt.executeUpdate(sql);
ResultSet rs = stmt.executeQuery(sql);

3.4 PreparedStatement

  表示預編譯的 SQL 語句的對象,SQL 語句已預編譯並存儲在 PreparedStatement 對象中。然後可以使用該對象多次有效地執行該語句。預編譯 SQL 時,參數用佔位符(?)佔位,等應用時再用實際參數替換佔位符(?)。

方法 描述
PreparedStatement Connection.prepareStatement​(String sql) 創建一個 PreparedStatement對象,用於將參數化的SQL語句發送到數據庫。
setXXX(參數1,參數2) 給預編譯SQL語句中的佔位符 ? 賦值

注意:

  • Xxx 可以爲任意基本類型,與數據庫中一致。
    • 參數1:佔位符(?)的位置,從1開始計數
    • 參數2:佔位符(?)的替換值

代碼應用片段:

//定義預編譯 SQL 語句,具體參數用佔位符(?)代替
String sql1 = "update account set a_money = a_money - ? where id = ?";
String sql2 = "update account set a_money = a_money + ? where id = ?";
//預編譯sql對象
PreparedStatement pstmt1 = conn.prepareStatement(sql1);
PreparedStatement pstmt2 = conn.prepareStatement(sql2);
//設置參數
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);

3.5 ResultSet

  代表數據庫結果集的數據表,通常通過執行查詢數據庫的語句來生成。

方法 描述
boolean next​() 向後移動遊標,判斷當前行是否有記錄,有則返回 true,反之返回false
getXxx() 獲取Xxx類型的數據

關於getXxx()方法的注意事項:

  • Xxx爲基本數據類型,如:getString()、getInt()等。
  • 參數可以是列的編號或者是列的名稱。

代碼應用片段

while(resultset.next()){
    int id = resultset.getInt(1);
    String name = resultset.getString("a_name");
    double money = resultset.getDouble(3);
    System.out.println(id + "---" + name + "---" + money);
}


4. 抽取 JDBC 的工具類

4.1 目的

  簡化代碼編寫,增加代碼的可維護性,將 JDBC 的基本操作放到一個工具類中,用配置文件來獲取連接信息,降低耦合。

4.2 操作

  在一個類中完成註冊驅動、獲取連接、釋放資源等 JDBC 相關操作,抽取一個方法獲取連接對象,用配置文件(jdbc.properties)的方式保存連接信息,讓工具類具有通用性。

4.3 配置文件的編寫

url=jdbc:mysql:///demo_test?serverTimezone=UTC
user=root
password=root
driver=com.mysql.cj.jdbc.Driver

4.4 工具類的編寫

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

/**
 * JDBC工具類
 */
public class JdbcUtils {
    //聲明成員變量,只有靜態變量才能被靜態方法訪問。
    private static String url;
    private static String user;
    private static String password;
    private static String driver;
    /**
     * 文件的讀取,只需要讀取一次即可拿到這些值,使用靜態代碼塊
     */
    static {
        //讀取資源文件,獲取值。
        try {
            //1. 創建Properties集合類
            Properties pro = new Properties();
            //獲取src路徑下的文件的方法————》類加載器 ClassLoader
            ClassLoader classLoader = JdbcUtils.class.getClassLoader();
            URL res = classLoader.getResource("jdbc.properties");
            String path = res.getPath();
            System.out.println(path);
            //2. 加載文件
            pro.load(new FileReader(path));
            //3. 獲取數據,賦值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //4. 註冊驅動
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    /**
     * 獲取連接的對象
     * @return 連接對象
     */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,user, password);
    }
    /**
     * 釋放資源
     * @param stmt
     * @param conn
     */
    public static void  close(Statement stmt, Connection conn){
        if (stmt != null){
            try {
                stmt.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if (conn != null){
            try {
                conn.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
    }
    /**
     * 釋放資源重載
     * @param rs
     * @param stmt
     * @param conn
     */
    public static void  close(ResultSet rs, Statement stmt, Connection conn){
        if (rs != null){
            try {
                rs.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if (stmt != null){
            try {
                stmt.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if (conn != null){
            try {
                conn.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
    }
}


5. 綜合實例

案例需求:完成張三和李四的轉賬操作,張三賬戶 -500 ,李四賬戶 +500

  1. 創建數據庫
-- 創建用戶賬單表
create table account(
  id INT PRIMARY KEY AUTO_INCREMENT,
  a_name varchar(30),
  a_money double
);

-- 添加張三、李四的賬戶
insert into account(id,a_name,a_money) values
(1,"張三",1000),
(2,"李四",1000);

-- 查詢表
select * from account;
  1. 編寫 jdbc.properties 配置文件,放在src目錄下。內如參照 JDBC工具類抽取。

  2. 編寫工具類,內容參照 JDBC 工具類抽取。

  3. 編寫主類

package base.jdbc;

import base.util.JdbcUtils;
import java.sql.*;
/**
 * 轉賬操作
 */
public class JdbcDemo8 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;
        try {
            //1.獲取連接
            conn = JdbcUtils.getConnection();
            //開啓事務管理
            conn.setAutoCommit(false);//值爲false開啓
            //2.定義sql
            //2.1 張三 - 500
            String sql1 = "update account set a_money = a_money - ? where id = ?";
            //2.2 李四 + 500
            String sql2 = "update account set a_money = a_money + ? where id = ?";
            //3. 獲取執行sql對象,預編譯,參數用 ? 佔位符
            pstmt1 = conn.prepareStatement(sql1);
            pstmt2 = conn.prepareStatement(sql2);
            //4.設置參數佔位符的參數
            pstmt1.setDouble(1,500);
            pstmt1.setInt(2,1);
            pstmt2.setDouble(1,500);
            pstmt2.setInt(2,2);
            //5.執行sql
            pstmt1.executeUpdate();
            pstmt2.executeUpdate();
            //提交改變
            conn.commit();
        } catch (Exception e) {
            try{
                if (conn != null) {
                    conn.rollback();
                }
            } catch (SQLException se){
                se.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            JdbcUtils.close(pstmt1,conn);
            JdbcUtils.close(pstmt2,null);
        }
    }
}
  1. 再次查詢表中內容
select * from account;


時間:2019年10月29日19:17:36


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