MySQL數據庫JDBC編程詳解流程

一、數據庫編程的必備條件

編程語言: 如Java、C++、C、Python等

數據庫: 如Oracle、MySQL、SQL Server等

數據庫驅動包: 不同的數據庫,要使用編程語言來操作時,就需要使用該數據庫廠商提供的數據庫驅動包。

如:MySQL提供瞭Java的驅動包mysql-connector-java,需要基於java操作MySQL即需要該驅動包。同樣的,要基於java操作Oracle數據庫則需要Oracle的數據庫驅動包ojdbc。

二、Java的數據庫編程:JDBC

JDBC,即Java Database Connectivity,java數據庫連接,是一種用於執行SQL語句的Java API,它是Java中的數據庫連接規范。 這個API由java.sql. *, javax.sql. * 包中的一些類和接口組成,它為java開發人員操作數據庫提供瞭一個標準的API,可以為多種關系數據庫提供統一訪問。

三、JDBC工作原理

JDBC為多種關系數據庫提供瞭統一訪問方式。作為特定廠商數據庫訪問API的一種高級抽象,它主要包含一些通用的接口類。

JDBC訪問數據庫層次結構:

我們使用一套JDBC編碼,在切換數據庫之後,Java操作數據庫的代碼可以不動(幾乎),數據庫驅動包要調整,sql因為有標準sql的部分,還有數據庫相關的關鍵字,如mysql中的limit等,這些也需要調整。

JDBC優勢:

Java語言訪問數據庫操作完全面向抽象接口編程

開發數據庫應用不用限定在特定的數據庫廠商的API

為Java操作不同的數據庫提供一種統一的規范,程序在不同數據庫的可移植性大大增強

四、JDBC開發步驟

1.創建一個普通的Java項目

2.下載mysql的驅動包

下載驅動包網址

我用的是5.1.xx版本的,說明:不同版本的數據庫驅動包,裡邊的類/接口可能不同

3.項目中添加數據庫驅動包(依賴)

驗證:寫Java代碼,可以使用mysql驅動包中的類/接口,才表示引入的依賴沒有問題。

4.測試:連接數據庫

註意:

1.一開始我們寫入forName時會飄紅,這裡先不用管,直接拋出異常。 alt+enter出現以下的界面,點擊第一個:

2.獲取數據庫連接:Connection接口,需要使用jdbc中的,不要使用mysql中的

3.MySQL數據連接的URL參數格式如下:

jdbc:mysql://服務器地址:端口/數據庫名?參數名=參數值

//加載JDBC驅動程序:反射的方式,這樣調用初始化com.mysql.jdbc.Driver類,
//即將該類加載到JVM方法區,並執行該類的靜態方法塊,靜態屬性
//數據庫驅動包就可以在這種操作下,執行對應的初始化工作(驅動)
Class.forName("com.mysql.jdbc.Driver");
//獲取數據庫連接:Connection接口,需要使用jdbc中的,不要使用mysql中的
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/kang?" +
                "user=root&password=010124&useUnicode=true&characterEncoding=UTF-8&useSSL=false");

五、JDBC操作步驟

1.獲取數據庫連接對象

Connection(jdbc中的接口)

2.使用數據庫連接對象來創建一個操作命令對象Statement,該對象是進行sql操作的抽象出來的對象

//通過連接對象創建操作命令對象Statement(使用jdbc中的),該對象是用於操作sql的一個抽象的對象
Statement s=conn.createStatement();

3.調用操作命令對象的方法來執行sql 查詢:executeQuery 更新操作(插入、修改、刪除):executeUpdate,返回值int,表示執行成功瞭幾條

//更新操作:調用executeUpdate方法,插入,修改,刪除都是
int n=s.executeUpdate("update exam_result set math=60 where id=1");
System.out.println("修改成功的數量:"+n);

4.如果是查詢操作,需要處理結果集對象 查詢,返回ResultSet結果集對象,這個結果集對象類似於數據結構中List<Map<String,Object>>

//查詢:
//(1)調用Statement操作命令對象的executeQuery(sql)
//(2)返回一個ResultSet結果集對象(查詢sql執行的結果集)
ResultSet r=s.executeQuery("select id,name,chinese,math,english from exam_result where id>3");
//處理結果:結果集可能是多行數據,需要遍歷來獲取
//調用next就移動到下一行,返回true代表改行有數據,返回false代表該行沒有數據
while(r.next()){//一直遍歷到最後
    //進入循環,代表操作遍歷的一行數據
    int id=r.getInt("id");
    String name=r.getString("name");
    int chinese=r.getInt("chinese");
    int math=r.getInt("math");
    int english=r.getInt("english");
    System.out.printf("id=%s,name=%s,chinese=%s,math=%s,english=%s\n"
    ,id,name,chinese,math,english);
        }

運行結果:

註解:

5.釋放資源 無論jdbc操作成功,還是出現異常,都需要釋放資源,要考慮出現異常對象還沒有完成初始化,還是null的情況,需要反向釋放資源。

public class JDBC {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Connection conn =null;
        Statement s=null;
        ResultSet r=null;
        try{
            //之前寫過的所有程序放到try裡邊
        }finally{//無論如何,都要釋放資源
            //釋放資源:
            //(1)無論什麼情況(異常)
            //(2)釋放的順序,和創建的順序要相反
            //(結果集對象,操作命令對象,數據庫連接對象)
            if(r!=null){
                r.close();
            }
            if(s!=null){
                s.close();
            }
            if(conn!=null){
                conn.close();
            }
        }
    }
}

六、優化JDBC的部分代碼

1.獲取數據庫連接對象

Connection接口實現類由數據庫提供,獲取Connection對象通常有兩種方式:

1.一種是通過DriverManager(驅動管理類)的靜態方法獲取 也就是上面我們提到的方法。

2.一種是通過DataSourse(數據源/數據庫連接池)對象獲取。實際應用中會使用DataSourse對象。

//先創建數據庫連接池,再通過連接池獲取數據庫連接對象
DataSource ds=new MysqlDataSource();
//創建數據庫連接池:初始化時,就會創建一定數量的數據庫連接,這些連接對象可以重復使用,效率更高
//整個url帶參數可以隻使用setURL方法,也可以用參數調用方法的方式來設置
((MysqlDataSource)ds).setURL("jdbc:mysql://localhost:3306/kang");
((MysqlDataSource)ds).setUser("root");
((MysqlDataSource)ds).setPassword("010124");
((MysqlDataSource)ds).setUseUnicode(true);
((MysqlDataSource)ds).setCharacterEncoding("UTF-8");
((MysqlDataSource)ds).setUseSSL(false);
conn = ds.getConnection();
System.out.println(conn);

兩者區別:

1.DriverManager類來獲取的Connection連接,是無法重復利用的,每次使用完以後釋放資源時,通過Connection.close()都是關閉物理連接

2.DataSourse提供連接池的支持。連接池在初始化時將創建一定數量的數據庫連接,這些鏈接是可以復用的,每次使用完數據庫連接,釋放資源調用connection.close()都是將Connection連接對象回收。效率更高。

2.操作命令對象Statement

Statement對象主要是將SQL語句發送到數據庫中,JDBC API中主要提供瞭三種Statement對象。

Statement: 用於執行不帶參數的簡單SQL語句(簡單的操作命令對象)

PreParedStatement:(預編譯的操作命令對象)

用於執行帶或者不帶參數的SQL語句

SQL語句會預編譯在數據庫系統

執行速度快於Statement對象

CallableStatement: 用於執行數據庫存儲過程的調用(存儲過程的操作命令對象) 存儲過程:就是寫一段sql代碼,裡邊可以寫變量,循環,條件判斷等等。

查詢操作:

s = conn.createStatement();
//查詢:模擬在頁面上,輸入學生姓名來搜索學生
//(1)調用Statement操作命令對象的executeQuery(sql)
//(2)返回一個ResultSet結果集對象(查詢sql執行的結果集)
String queryName="孫權";//能正常查詢的輸入
//(1)調用Statement操作命令對象的executeQuery(sql)
//(2)返回一個ResultSet結果集對象(查詢sql執行的結果集)
String sql="select id,name,chinese,math,english from exam_result where name='"+queryName+"'";
System.out.println(sql);
r = s.executeQuery(sql);
while (r.next()) {//一直遍歷到最後
    //進入循環,代表操作遍歷的一行數據
    int id = r.getInt("id");
    String name = r.getString("name");
    int chinese = r.getInt("chinese");
    int math = r.getInt("math");
    int english = r.getInt("english");
    System.out.printf("id=%s,name=%s,chinese=%s,math=%s,english=%s\n", id, name, chinese, math, english);
    }

輸出結果:

但是這裡有一個現象: 如果我們把這裡的queryName改為“skdj’ or ‘1’=’1”,在拼接sql字符串時,就可能出現安全問題。 輸出結果為:

後面的‘1’=‘1’是一個恒為真的條件,所以就會造成整個or條件結果為真,輸出所有成員。 要解決以上安全問題,需要調整以上操作命令對象那個為PreparedStatement,並且使用占位符。

//要解決以上安全問題,需要調整以上操作命令對象那個為PreparedStatement
String queryName="skeij' or '1'='1";
int queryId=6;
//準備一個帶?占位符的sql
String sql="select id,name,chinese,math,english from exam_result where name=? or id=?";
ps=conn.prepareStatement(sql);//創建預編譯的操作命令對象
//替換占位符:調用setXXX方法,第一個參數,表示第幾個占位符(從1開始),第二個參數,表示要替換的值
ps.setString(1,queryName);//替換的值是什麼類型,就調用setXXX方法
ps.setInt(2,queryId);

//執行sql,需要使用無參的方法
r=ps.executeQuery();

輸出結果為:

插入操作:

int queryId=7;
String queryName="圖圖";
int chinese=60;
int math=98;
int english=79;
String sql="insert into exam_result values(?,?,?,?,?)";
ps=conn.prepareStatement(sql);
ps.setInt(1,queryId);
ps.setString(2,queryName);
ps.setInt(3,chinese);
ps.setInt(4,math);
ps.setInt(5,english);

//executeUpdate()方法返回值是一個整數,指示受影響的行數,通常用於update,insert,delete語句。
int ret=ps.executeUpdate();
System.out.println(ret);

其餘的刪除,更新操作都與上面類似,這裡不再過多演示。

3.ResultSet對象

ResultSet對象它被成為結果集,他代表符合SQL語句條件的所有行,並且它通過一套getXXX方法提供瞭對這些行中數據的訪問。 ResultSet裡的數據一行一行排列,每行有多個字段,並且有一個記錄指針,指針所指的數據叫做當前數據行,我們隻能來操作當前的數據行。如果想要取得某一條記錄,就要使用ResultSet的next()方法,如果我們想要得到ResultSet裡的所有記錄,就應該使用while循環。

//處理結果:結果集可能是多行數據,需要遍歷來獲取
//調用next就移動到下一行,返回true代表改行有數據,返回false代表該行沒有數據
while (r.next()) {//一直遍歷到最後
    //進入循環,代表操作遍歷的一行數據
    int id = r.getInt("id");
    String name = r.getString("name");
    int chinese = r.getInt("chinese");
    int math = r.getInt("math");
    int english = r.getInt("english");
    System.out.printf("id=%s,name=%s,chinese=%s,math=%s,english=%s\n", id, name, chinese, math, english);
    }

4.總結

主要掌握兩種執行SQL的方法:

1.executeQuery()方法執行後返回單個結果集的,通常用於select語句。

2.executeUpdate()方法返回值是一個整數,指示受影響的行數,通常用於update、insert、delete語句。

PreparedStatement註意事項:

1.參數化SQL查詢

2.占位符不能使用多值

3.占位符:?下標從1開始

4.阻止常見SQL註入攻擊

5.SQL預編譯

6.性能比Statement高

到此這篇關於MySQL數據庫JDBC編程詳解流程的文章就介紹到這瞭,更多相關MySQL JDBC內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: