JDBC(Java DataBase Connection)

1.1JDBC概述

JDBC(Java?Data?Base?Connectivity,java數(shù)據(jù)庫連接)是一種用于執(zhí)行SQL語句的Java?API,可以為多種關(guān)系數(shù)據(jù)庫提供統(tǒng)一訪問,它由一組用Java語言編寫的類和接口組成。是Java訪問數(shù)據(jù)庫的標(biāo)準(zhǔn)規(guī)范

JDBC提供了一種基準(zhǔn),據(jù)此可以構(gòu)建更高級的工具和接口,使數(shù)據(jù)庫開發(fā)人員能夠編寫數(shù)據(jù)庫應(yīng)用程序。

JDBC需要連接驅(qū)動,驅(qū)動是兩個設(shè)備要進(jìn)行通信,滿足一定通信數(shù)據(jù)格式,數(shù)據(jù)格式由設(shè)備提供商規(guī)定,設(shè)備提供商為設(shè)備提供驅(qū)動軟件,通過軟件可以與該設(shè)備進(jìn)行通信。

1.2JDBC原理

Java提供訪問數(shù)據(jù)庫規(guī)范稱為JDBC,而生產(chǎn)廠商提供規(guī)范的實現(xiàn)類稱為驅(qū)動。


JDBC是接口,驅(qū)動是接口的實現(xiàn),沒有驅(qū)動將無法完成數(shù)據(jù)庫連接,從而不能操作數(shù)據(jù)庫!每個數(shù)據(jù)庫廠商都需要提供自己的驅(qū)動,用來連接自己公司的數(shù)據(jù)庫,也就是說驅(qū)動一般都由數(shù)據(jù)庫生成廠商提供。

1.3JDBC開發(fā)步驟

1.注冊驅(qū)動.

2.獲得連接.

3.獲得語句執(zhí)行平臺

4.執(zhí)行sql語句

5.處理結(jié)果

6.釋放資源.

1.3.1導(dǎo)入驅(qū)動jar包

創(chuàng)建lib目錄,用于存放當(dāng)前項目需要的所有jar包

選擇jar包,右鍵執(zhí)行build?path?/?Add?to?Build?Path

1.3.2API詳解:注冊驅(qū)動

代碼:Class.forName("com.mysql.jdbc.Driver");

JDBC規(guī)范定義驅(qū)動接口:java.sql.Driver,MySql驅(qū)動包提供了實現(xiàn)類:com.mysql.jdbc.Driver

DriverManager工具類,提供注冊驅(qū)動的方法registerDriver(),方法的參數(shù)是java.sql.Driver,所以我們可以通過如下語句進(jìn)行注冊:

DriverManager.registerDriver(new?com.mysql.jdbc.Driver());

以上代碼不推薦使用,存在兩方面不足

1.硬編碼,后期不易于程序擴(kuò)展和維護(hù)

2.驅(qū)動被注冊兩次。

通常開發(fā)我們使用Class.forName()加載一個使用字符串描述的驅(qū)動類。

如果使用Class.forName()將類加載到內(nèi)存,該類的靜態(tài)代碼將自動執(zhí)行。

通過查詢com.mysql.jdbc.Driver源碼,我們發(fā)現(xiàn)Driver類“主動”將自己進(jìn)行注冊

public?class?Driver?extends?NonRegisteringDriver?implements?java.sql.Driver?{

static?{

try?{

java.sql.DriverManager.registerDriver(new?Driver());

}?catch?(SQLException?E)?{

throw?new?RuntimeException("Can't?register?driver!");

}

}

……

}

1.3.3API詳解:獲得鏈接

代碼:Connection?con?=?DriverManager.getConnection

(“jdbc:mysql://localhost:3306/mydb”,”root”,”root”);

獲取連接需要方法DriverManager.getConnection(url,username,password),三個參數(shù)分別表示,url需要連接數(shù)據(jù)庫的位置(網(wǎng)址)user用戶名password密碼

url比較復(fù)雜,下面是mysql的url:

jdbc:mysql://localhost:3306/mydb

JDBC規(guī)定url的格式由三部分組成,每個部分中間使用冒號分隔。

l第一部分是jdbc,這是固定的;

l第二部分是數(shù)據(jù)庫名稱,那么連接mysql數(shù)據(jù)庫,第二部分當(dāng)然是mysql了;

l第三部分是由數(shù)據(jù)庫廠商規(guī)定的,我們需要了解每個數(shù)據(jù)庫廠商的要求,mysql的第三部分分別由數(shù)據(jù)庫服務(wù)器的IP地址(localhost)、端口號(3306),以及DATABASE名稱(mydb)組成。

1.3.4API詳解:獲得語句執(zhí)行平臺

String?sql?=?"某SQL語句";

獲取Statement語句執(zhí)行平臺:Statement?stmt?=?con.createStatement();

常用方法:

nint?executeUpdate(String?sql);?--執(zhí)行insert?update?delete語句.

nResultSet?executeQuery(String?sql);?--執(zhí)行select語句.

nboolean?execute(String?sql);?--執(zhí)行select返回true執(zhí)行其他的語句返回false.

1.3.5API詳解:處理結(jié)果集(執(zhí)行insert、update、delete無需處理)

ResultSet實際上就是一張二維的表格,我們可以調(diào)用其boolean?next()方法指向某行記錄,當(dāng)?shù)谝淮握{(diào)用next()方法時,便指向第一行記錄的位置,這時就可以使用ResultSet提供的getXXX(int?col)方法(與索引從0開始不同個,列從1開始)來獲取指定列的數(shù)據(jù):

rs.next();//指向第一行

rs.getInt(1);//獲取第一行第一列的數(shù)據(jù)

常用方法:

nObject?getObject(intindex)/?Object?getObject(String?name)獲得任意對象

nString?getString(intindex)/?Object?getObject(String?name)獲得字符串

nint?getInt(intindex)/?Object?getObject(String?name)獲得整形

ndouble?getDouble(intindex)/?Object?getObject(String?name)獲得雙精度浮點型

1.3.6API詳解:釋放資源

與IO流一樣,使用后的東西都需要關(guān)閉!關(guān)閉的順序是先得到的后關(guān)閉,后得到的先關(guān)閉。

rs.close();

stmt.close();

con.close();

1.4SQL注入問題

假設(shè)有登錄案例SQL語句如下:

SELECT?*?FROM用戶表WHERE?NAME?=用戶輸入的用戶名AND?PASSWORD?=用戶輸?shù)拿艽a;

此時,當(dāng)用戶輸入正確的賬號與密碼后,查詢到了信息則讓用戶登錄。但是當(dāng)用戶輸入的賬號為XXX密碼為:XXX’OR‘a(chǎn)’=’a時,則真正執(zhí)行的代碼變?yōu)椋?/p>

SELECT?*?FROM用戶表WHERE?NAME?=‘XXX’AND?PASSWORD?=’XXX’OR’a’=’a’;

此時,上述查詢語句時永遠(yuǎn)可以查詢出結(jié)果的。那么用戶就直接登錄成功了,顯然我們不希望看到這樣的結(jié)果,這便是SQL注入問題。

為此,我們使用PreparedStatement來解決對應(yīng)的問題。

1.5API詳解:預(yù)處理對象

使用PreparedStatement預(yù)處理對象時,建議每條sql語句所有的實際參數(shù),都使用逗號分隔。

String?sql?=?"insert?into?sort(sid,sname)?values(?,?)";;

PreparedStatement預(yù)處理對象代碼:

PreparedStatement?psmt?=?conn.prepareStatement(sql)

常用方法:

1.執(zhí)行SQL語句:

lint?executeUpdate();?--執(zhí)行insert?update?delete語句.

lResultSet?executeQuery();?--執(zhí)行select語句.

lboolean?execute();?--執(zhí)行select返回true?執(zhí)行其他的語句返回false.

2.設(shè)置實際參數(shù)

lvoidsetXxx(intindex,Xxxxx)?將指定參數(shù)設(shè)置為給定Java的xx值。在將此值發(fā)送到數(shù)據(jù)庫時,驅(qū)動程序?qū)⑺D(zhuǎn)換成一個?SQLXxx類型值。

例如:

setString(2,?"家用電器")把SQL語句中第2個位置的占位符??替換成實際參數(shù)"家用電器"

1.6預(yù)處理對象executeUpdate方法

通過預(yù)處理對象的executeUpdate方法,完成記錄的insert\update\delete語句的執(zhí)行。操作格式統(tǒng)一如下:

1.注冊驅(qū)動

2.獲取連接

3.獲取預(yù)處理對象

4.?SQL語句占位符設(shè)置實際參數(shù)

5.執(zhí)行SQL語句

6.釋放資源

1.6.1插入記錄:insert

l實現(xiàn)向分類表中插入指定的新分類

publicvoiddemo01()throwsException?{

//?1注冊驅(qū)動

Class.forName("com.mysql.jdbc.Driver");

//?2獲取連接

Connectionconn=?DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","root");

//?3獲得預(yù)處理對象

Stringsql="insert?into?sort(sname)?values(?)";

PreparedStatementstat=conn.prepareStatement(sql);

//?4SQL語句占位符設(shè)置實際參數(shù)

stat.setString(1,"奢侈品");

//?5執(zhí)行SQL語句

intline=stat.executeUpdate();

System.out.println("新添加記錄數(shù):"+line);

//6釋放資源

stat.close();

conn.close();

}

1.6.2更新記錄:update

l實現(xiàn)更新分類表中指定分類ID所對應(yīng)記錄的分類名稱

publicvoiddemo02()throwsException?{

//?1注冊驅(qū)動

Class.forName("com.mysql.jdbc.Driver");

//?2獲取連接

Connectionconn=?DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","root");

//?3獲得預(yù)處理對象中

Stringsql="update?sort?set?sname=??where?sid=?";

PreparedStatementstat=conn.prepareStatement(sql);

//?4SQL語句占位符設(shè)置實際參數(shù)

stat.setString(1,"數(shù)碼產(chǎn)品");

stat.setInt(2,?1);

//?5執(zhí)行SQL語句

intline=stat.executeUpdate();

System.out.println("更新記錄數(shù):"+line);

//6釋放資源

stat.close();

conn.close();

}

1.6.3刪除記錄:delete

l實現(xiàn)刪除分類表中指定分類ID的記錄

publicvoiddemo03()throwsException?{

//?1注冊驅(qū)動

Class.forName("com.mysql.jdbc.Driver");

//?2獲取連接

Connectionconn=?DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","root");

//?3獲得預(yù)處理對象

Stringsql="delete?from?sort?where?sid=?";

PreparedStatementstat=conn.prepareStatement(sql);

//?4SQL語句占位符設(shè)置實際參數(shù)

stat.setInt(1,?1);

//?5執(zhí)行SQL語句

intline=stat.executeUpdate();

System.out.println("刪除記錄數(shù):"+line);

//6釋放資源

stat.close();

conn.close();

}

1.7預(yù)處理對象executeQuery方法

通過預(yù)處理對象的executeQuery方法,完成記錄的select語句的執(zhí)行。操作格式統(tǒng)一如下:

1.注冊驅(qū)動

2.獲取連接

3.獲取預(yù)處理對象

4.?SQL語句占位符設(shè)置實際參數(shù)

5.執(zhí)行SQL語句

6.處理結(jié)果集(遍歷結(jié)果集合)

7.釋放資源

1.7.1查詢記錄:select

l實現(xiàn)查詢分類表所有記錄

publicvoiddemo04()throwsException?{

//?1注冊驅(qū)動

Class.forName("com.mysql.jdbc.Driver");

//?2獲取連接

Connectionconn=?DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","root");

//?3獲得預(yù)處理對象

Stringsql="select?*?from?sort";

PreparedStatementstat=conn.prepareStatement(sql);

//?4SQL語句占位符設(shè)置實際參數(shù)

//?5執(zhí)行SQL語句

ResultSetrs=stat.executeQuery();

//6處理結(jié)果集(遍歷結(jié)果集合)

while(rs.next()?){

//獲取當(dāng)前行的分類ID

Stringsid=rs.getString("sid");//方法參數(shù)為數(shù)據(jù)庫表中的列名

//獲取當(dāng)前行的分類名稱

Stringsname=rs.getString("sname");

//顯示數(shù)據(jù)

System.out.println(sid+"-----"+sname);

}

//7釋放資源

rs.close();

stat.close();

conn.close();

}

l實現(xiàn)查詢分類表中指定分類名稱的記錄

publicvoiddemo05()throwsException?{

//?1注冊驅(qū)動

Class.forName("com.mysql.jdbc.Driver");

//?2獲取連接

Connectionconn=?DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","root");

//?3獲得預(yù)處理對象

Stringsql="select?*?from?sort?where?sname=?";

PreparedStatementstat=conn.prepareStatement(sql);

//?4SQL語句占位符設(shè)置實際參數(shù)

stat.setString(1,"奢侈品");

//5執(zhí)行SQL語句

ResultSetrs=stat.executeQuery();

//6處理結(jié)果集(遍歷結(jié)果集合)

while(rs.next()?){

//獲取當(dāng)前行的分類ID

Stringsid=rs.getString("sid");//方法參數(shù)為數(shù)據(jù)庫表中的列名

//獲取當(dāng)前行的分類名稱

Stringsname=rs.getString("sname");

//顯示數(shù)據(jù)

System.out.println(sid+"-----"+sname);

}

//7釋放資源

rs.close();

stat.close();

conn.close();

}

1.8JDBC工具類

“獲得數(shù)據(jù)庫連接”操作,將在以后的增刪改查所有功能中都存在,可以封裝工具類JDBCUtils。提供獲取連接對象的方法,從而達(dá)到代碼的重復(fù)利用。

該工具類提供方法:public?static?Connection?getConn?()。代碼如下:

/*

*?JDBC工具類

*/

publicclassJDBCUtils?{

publicstaticfinalStringDRIVERNAME="com.mysql.jdbc.Driver";

publicstaticfinalStringURL="jdbc:mysql://localhost:3306/mydb";

publicstaticfinalStringUSER="root";

publicstaticfinalStringPASSWORD="root";

static{

try{

Class.forName(DRIVERNAME);

}catch(ClassNotFoundExceptione)?{

System.out.println("數(shù)據(jù)庫驅(qū)動注冊失??!");

}

}

//提供獲取連接的方法

publicstaticConnection?getConn()throwsException?{

//?2.獲得連接

Connectionconn=?DriverManager.getConnection(URL,USER,PASSWORD);

//返回連接

returnconn;

}

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • JDBC簡介 SUN公司為了簡化、統(tǒng)一對數(shù)據(jù)庫的操作,定義了一套Java操作數(shù)據(jù)庫的規(guī)范,稱之為JDBC。JDBC...
    奮斗的老王閱讀 1,638評論 0 51
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,734評論 18 399
  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 6,248評論 0 4
  • 1、青梅糖漬發(fā)酵 隨便果的載體青梅依靠大自然的饋贈,至少發(fā)酵四個月以上的時間,緩慢但是很有力量。把最奢侈的時間,“...
    向日葵ll閱讀 3,374評論 0 0
  • 今天是六一兒童節(jié),似乎不寫點關(guān)于兒童的文章,就對不起自己幼兒教師的身份。所以寫下了以下幾點關(guān)于孩子教育的觀點。 ...
    阿寶的育兒寶典閱讀 496評論 0 2

友情鏈接更多精彩內(nèi)容