MySQL數(shù)據(jù)庫JDBC編程詳解流程
一、數(shù)據(jù)庫編程的必備條件
編程語言: 如Java、C++、C、Python等
數(shù)據(jù)庫: 如Oracle、MySQL、SQL Server等
數(shù)據(jù)庫驅(qū)動包: 不同的數(shù)據(jù)庫,要使用編程語言來操作時,就需要使用該數(shù)據(jù)庫廠商提供的數(shù)據(jù)庫驅(qū)動包。
如:MySQL提供了Java的驅(qū)動包mysql-connector-java,需要基于java操作MySQL即需要該驅(qū)動包。同樣的,要基于java操作Oracle數(shù)據(jù)庫則需要Oracle的數(shù)據(jù)庫驅(qū)動包ojdbc。
二、Java的數(shù)據(jù)庫編程:JDBC
JDBC,即Java Database Connectivity,java數(shù)據(jù)庫連接,是一種用于執(zhí)行SQL語句的Java API,它是Java中的數(shù)據(jù)庫連接規(guī)范。 這個API由java.sql. *, javax.sql. * 包中的一些類和接口組成,它為java開發(fā)人員操作數(shù)據(jù)庫提供了一個標(biāo)準(zhǔn)的API,可以為多種關(guān)系數(shù)據(jù)庫提供統(tǒng)一訪問。
三、JDBC工作原理
JDBC為多種關(guān)系數(shù)據(jù)庫提供了統(tǒng)一訪問方式。作為特定廠商數(shù)據(jù)庫訪問API的一種高級抽象,它主要包含一些通用的接口類。
JDBC訪問數(shù)據(jù)庫層次結(jié)構(gòu):
我們使用一套JDBC編碼,在切換數(shù)據(jù)庫之后,Java操作數(shù)據(jù)庫的代碼可以不動(幾乎),數(shù)據(jù)庫驅(qū)動包要調(diào)整,sql因為有標(biāo)準(zhǔn)sql的部分,還有數(shù)據(jù)庫相關(guān)的關(guān)鍵字,如mysql中的limit等,這些也需要調(diào)整。
JDBC優(yōu)勢:
Java語言訪問數(shù)據(jù)庫操作完全面向抽象接口編程
開發(fā)數(shù)據(jù)庫應(yīng)用不用限定在特定的數(shù)據(jù)庫廠商的API
為Java操作不同的數(shù)據(jù)庫提供一種統(tǒng)一的規(guī)范,程序在不同數(shù)據(jù)庫的可移植性大大增強(qiáng)
四、JDBC開發(fā)步驟
1.創(chuàng)建一個普通的Java項目
2.下載mysql的驅(qū)動包
我用的是5.1.xx版本的,說明:不同版本的數(shù)據(jù)庫驅(qū)動包,里邊的類/接口可能不同
3.項目中添加數(shù)據(jù)庫驅(qū)動包(依賴)
驗證:寫Java代碼,可以使用mysql驅(qū)動包中的類/接口,才表示引入的依賴沒有問題。
4.測試:連接數(shù)據(jù)庫
注意:
1.一開始我們寫入forName時會飄紅,這里先不用管,直接拋出異常。 alt+enter出現(xiàn)以下的界面,點擊第一個:
2.獲取數(shù)據(jù)庫連接:Connection接口,需要使用jdbc中的,不要使用mysql中的
3.MySQL數(shù)據(jù)連接的URL參數(shù)格式如下:
jdbc:mysql://服務(wù)器地址:端口/數(shù)據(jù)庫名?參數(shù)名=參數(shù)值
//加載JDBC驅(qū)動程序:反射的方式,這樣調(diào)用初始化com.mysql.jdbc.Driver類, //即將該類加載到JVM方法區(qū),并執(zhí)行該類的靜態(tài)方法塊,靜態(tài)屬性 //數(shù)據(jù)庫驅(qū)動包就可以在這種操作下,執(zhí)行對應(yīng)的初始化工作(驅(qū)動) Class.forName("com.mysql.jdbc.Driver"); //獲取數(shù)據(jù)庫連接: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.獲取數(shù)據(jù)庫連接對象
Connection(jdbc中的接口)
2.使用數(shù)據(jù)庫連接對象來創(chuàng)建一個操作命令對象Statement,該對象是進(jìn)行sql操作的抽象出來的對象
//通過連接對象創(chuàng)建操作命令對象Statement(使用jdbc中的),該對象是用于操作sql的一個抽象的對象 Statement s=conn.createStatement();
3.調(diào)用操作命令對象的方法來執(zhí)行sql 查詢:executeQuery 更新操作(插入、修改、刪除):executeUpdate,返回值int,表示執(zhí)行成功了幾條
//更新操作:調(diào)用executeUpdate方法,插入,修改,刪除都是 int n=s.executeUpdate("update exam_result set math=60 where id=1"); System.out.println("修改成功的數(shù)量:"+n);
4.如果是查詢操作,需要處理結(jié)果集對象 查詢,返回ResultSet結(jié)果集對象,這個結(jié)果集對象類似于數(shù)據(jù)結(jié)構(gòu)中List<Map<String,Object>>
//查詢: //(1)調(diào)用Statement操作命令對象的executeQuery(sql) //(2)返回一個ResultSet結(jié)果集對象(查詢sql執(zhí)行的結(jié)果集) ResultSet r=s.executeQuery("select id,name,chinese,math,english from exam_result where id>3"); //處理結(jié)果:結(jié)果集可能是多行數(shù)據(jù),需要遍歷來獲取 //調(diào)用next就移動到下一行,返回true代表改行有數(shù)據(jù),返回false代表該行沒有數(shù)據(jù) while(r.next()){//一直遍歷到最后 //進(jìn)入循環(huán),代表操作遍歷的一行數(shù)據(jù) 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); }
運行結(jié)果:
注解:
5.釋放資源 無論jdbc操作成功,還是出現(xiàn)異常,都需要釋放資源,要考慮出現(xiàn)異常對象還沒有完成初始化,還是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)釋放的順序,和創(chuàng)建的順序要相反 //(結(jié)果集對象,操作命令對象,數(shù)據(jù)庫連接對象) if(r!=null){ r.close(); } if(s!=null){ s.close(); } if(conn!=null){ conn.close(); } } } }
六、優(yōu)化JDBC的部分代碼
1.獲取數(shù)據(jù)庫連接對象
Connection接口實現(xiàn)類由數(shù)據(jù)庫提供,獲取Connection對象通常有兩種方式:
1.一種是通過DriverManager(驅(qū)動管理類)的靜態(tài)方法獲取 也就是上面我們提到的方法。
2.一種是通過DataSourse(數(shù)據(jù)源/數(shù)據(jù)庫連接池)對象獲取。實際應(yīng)用中會使用DataSourse對象。
//先創(chuàng)建數(shù)據(jù)庫連接池,再通過連接池獲取數(shù)據(jù)庫連接對象 DataSource ds=new MysqlDataSource(); //創(chuàng)建數(shù)據(jù)庫連接池:初始化時,就會創(chuàng)建一定數(shù)量的數(shù)據(jù)庫連接,這些連接對象可以重復(fù)使用,效率更高 //整個url帶參數(shù)可以只使用setURL方法,也可以用參數(shù)調(diào)用方法的方式來設(shè)置 ((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);
兩者區(qū)別:
1.DriverManager類來獲取的Connection連接,是無法重復(fù)利用的,每次使用完以后釋放資源時,通過Connection.close()都是關(guān)閉物理連接
2.DataSourse提供連接池的支持。連接池在初始化時將創(chuàng)建一定數(shù)量的數(shù)據(jù)庫連接,這些鏈接是可以復(fù)用的,每次使用完數(shù)據(jù)庫連接,釋放資源調(diào)用connection.close()都是將Connection連接對象回收。效率更高。
2.操作命令對象Statement
Statement對象主要是將SQL語句發(fā)送到數(shù)據(jù)庫中,JDBC API中主要提供了三種Statement對象。
Statement: 用于執(zhí)行不帶參數(shù)的簡單SQL語句(簡單的操作命令對象)
PreParedStatement:(預(yù)編譯的操作命令對象)
用于執(zhí)行帶或者不帶參數(shù)的SQL語句
SQL語句會預(yù)編譯在數(shù)據(jù)庫系統(tǒng)
執(zhí)行速度快于Statement對象
CallableStatement: 用于執(zhí)行數(shù)據(jù)庫存儲過程的調(diào)用(存儲過程的操作命令對象) 存儲過程:就是寫一段sql代碼,里邊可以寫變量,循環(huán),條件判斷等等。
查詢操作:
s = conn.createStatement(); //查詢:模擬在頁面上,輸入學(xué)生姓名來搜索學(xué)生 //(1)調(diào)用Statement操作命令對象的executeQuery(sql) //(2)返回一個ResultSet結(jié)果集對象(查詢sql執(zhí)行的結(jié)果集) String queryName="孫權(quán)";//能正常查詢的輸入 //(1)調(diào)用Statement操作命令對象的executeQuery(sql) //(2)返回一個ResultSet結(jié)果集對象(查詢sql執(zhí)行的結(jié)果集) 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()) {//一直遍歷到最后 //進(jìn)入循環(huán),代表操作遍歷的一行數(shù)據(jù) 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); }
輸出結(jié)果:
但是這里有一個現(xiàn)象: 如果我們把這里的queryName改為“skdj’ or ‘1’='1”,在拼接sql字符串時,就可能出現(xiàn)安全問題。 輸出結(jié)果為:
后面的‘1’=‘1’是一個恒為真的條件,所以就會造成整個or條件結(jié)果為真,輸出所有成員。 要解決以上安全問題,需要調(diào)整以上操作命令對象那個為PreparedStatement,并且使用占位符。
//要解決以上安全問題,需要調(diào)整以上操作命令對象那個為PreparedStatement String queryName="skeij' or '1'='1"; int queryId=6; //準(zhǔn)備一個帶?占位符的sql String sql="select id,name,chinese,math,english from exam_result where name=? or id=?"; ps=conn.prepareStatement(sql);//創(chuàng)建預(yù)編譯的操作命令對象 //替換占位符:調(diào)用setXXX方法,第一個參數(shù),表示第幾個占位符(從1開始),第二個參數(shù),表示要替換的值 ps.setString(1,queryName);//替換的值是什么類型,就調(diào)用setXXX方法 ps.setInt(2,queryId); //執(zhí)行sql,需要使用無參的方法 r=ps.executeQuery();
輸出結(jié)果為:
插入操作:
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()方法返回值是一個整數(shù),指示受影響的行數(shù),通常用于update,insert,delete語句。 int ret=ps.executeUpdate(); System.out.println(ret);
其余的刪除,更新操作都與上面類似,這里不再過多演示。
3.ResultSet對象
ResultSet對象它被成為結(jié)果集,他代表符合SQL語句條件的所有行,并且它通過一套getXXX方法提供了對這些行中數(shù)據(jù)的訪問。 ResultSet里的數(shù)據(jù)一行一行排列,每行有多個字段,并且有一個記錄指針,指針?biāo)傅臄?shù)據(jù)叫做當(dāng)前數(shù)據(jù)行,我們只能來操作當(dāng)前的數(shù)據(jù)行。如果想要取得某一條記錄,就要使用ResultSet的next()方法,如果我們想要得到ResultSet里的所有記錄,就應(yīng)該使用while循環(huán)。
//處理結(jié)果:結(jié)果集可能是多行數(shù)據(jù),需要遍歷來獲取 //調(diào)用next就移動到下一行,返回true代表改行有數(shù)據(jù),返回false代表該行沒有數(shù)據(jù) while (r.next()) {//一直遍歷到最后 //進(jìn)入循環(huán),代表操作遍歷的一行數(shù)據(jù) 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.總結(jié)
主要掌握兩種執(zhí)行SQL的方法:
1.executeQuery()方法執(zhí)行后返回單個結(jié)果集的,通常用于select語句。
2.executeUpdate()方法返回值是一個整數(shù),指示受影響的行數(shù),通常用于update、insert、delete語句。
PreparedStatement注意事項:
1.參數(shù)化SQL查詢
2.占位符不能使用多值
3.占位符:?下標(biāo)從1開始
4.阻止常見SQL注入攻擊
5.SQL預(yù)編譯
6.性能比Statement高
到此這篇關(guān)于MySQL數(shù)據(jù)庫JDBC編程詳解流程的文章就介紹到這了,更多相關(guān)MySQL JDBC內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
連接MySQL出現(xiàn)Host is not allowed to con
這篇文章主要給大家介紹了連接MySQL出現(xiàn)Host is not allowed to connect to this MySQL server 解決方法,文中有詳細(xì)的解決步驟,需要的朋友可以參考下2023-08-08圖解Mysql中的LEFT?JOIN、RIGHT?JOIN與JOIN的區(qū)別
這篇文章主要介紹了圖解Mysql中的LEFT?JOIN、RIGHT?JOIN與JOIN的區(qū)別,Left?Join就是以左邊為基準(zhǔn),Inner?Join就是查兩個重復(fù)的部分,Right?Join就是以右邊為基準(zhǔn),需要的朋友可以參考下2023-11-11Mysql使用存儲過程快速添加百萬數(shù)據(jù)的示例代碼
這篇文章主要介紹了Mysql使用存儲過程快速添加百萬數(shù)據(jù),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08Mysql數(shù)據(jù)庫名和表名在不同系統(tǒng)下的大小寫敏感問題
在 MySQL 中,數(shù)據(jù)庫和表對應(yīng)于那些目錄下的目錄和文件。因而,操作系統(tǒng)的敏感性決定數(shù)據(jù)庫和表命名的大小寫敏感。2011-01-01mysql 加了 skip-name-resolve不能鏈接數(shù)據(jù)庫問題的解決方法
這篇文章主要介紹了mysql 加了 skip-name-resolve不能鏈接數(shù)據(jù)庫問題的解決方法,需要的朋友可以參考下2016-04-04mysql遇到load data導(dǎo)入文件數(shù)據(jù)出現(xiàn)1290錯誤的解決方案
這篇文章主要介紹了mysql遇到load data導(dǎo)入文件數(shù)據(jù)出現(xiàn)1290錯誤的解決方案,非常的簡單實用,有需要的小伙伴可以參考下2018-07-07