JDBC有这一篇就够了(万字JDBC附代码详解)
目錄:
1.JDBC的本質(zhì)
2.JDBC的使用步驟
3.DriverManager對(duì)象
4.Connectioin對(duì)象
5.Statement對(duì)象
6.ResultSet對(duì)象
7.JDBC工具類
8.PreparedStatement類
9.JDBC管理事務(wù)
1.JDBC的本質(zhì)
Java DataBase Connectivity(Java語(yǔ)言連接數(shù)據(jù)庫(kù))
JDBC是SUN公司制定的一套接口(interface)
2.JDBC的使用步驟
第一步:注冊(cè)驅(qū)動(dòng)(作用:告訴Java程序,即將要連接的是哪個(gè)品牌的數(shù)據(jù)庫(kù))
第二步:獲取連接(表示JVM的進(jìn)程和數(shù)據(jù)庫(kù)進(jìn)程之間的通道打開(kāi)了,這屬于進(jìn)程之間的通信,重量級(jí)的,使用完之后一定要關(guān)閉通道。)
第三步:獲取數(shù)據(jù)庫(kù)操作對(duì)象(專門執(zhí)行sql語(yǔ)句的對(duì)象)
第四步:執(zhí)行SQL語(yǔ)句(DQL DML…)
第五步:處理查詢結(jié)果集(只有當(dāng)?shù)谒牟綀?zhí)行的是select語(yǔ)句的時(shí)候,才有這第五步處理查詢結(jié)果集。)
第六步:釋放資源(使用完資源之后一定要關(guān)閉資源。Java和數(shù)據(jù)庫(kù)屬于進(jìn)程間的通信,開(kāi)啟之后一定要關(guān)閉。)
代碼模版:
package testJdbc;import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement;public class test2 {public static void main(String[] args) throws SQLException, ClassNotFoundException {//1、注冊(cè)驅(qū)動(dòng)String JDBCDriver = "com.mysql.jdbc.Driver";Class.forName(JDBCDriver);//2、連接數(shù)據(jù)庫(kù)String url="jdbc:mysql://127.0.0.1:3306/school"; //鏈接數(shù)據(jù)的urlString user="root"; //登錄數(shù)據(jù)庫(kù)的用戶名String password="123456"; //用戶的密碼Connection conn = DriverManager.getConnection(url, user, password);Statement st = conn.createStatement();//一、查詢sqlString sql="select * from student";ResultSet rs = st.executeQuery(sql);System.out.println("SId"+" "+"Sname"+" "+"Sage"+" "+"Ssex");while (rs.next()) {System.out.println(rs.getString("SId")+" "+rs.getString("Sname")+" "+rs.getString("Sage")+" "+rs.getString("Ssex"));}/*//二、修改數(shù)據(jù)int update = st.executeUpdate("update student set Sname='xiaolizi' where SId=2");System.out.println("修改后成功的條數(shù):"+update);*///三、刪除//st.execute("delete from student where SId='2'");//四、添加數(shù)據(jù) // String sql1 = "insert into student(SId,Sname,Sage,Ssex) values('4','鄭','3','2')"; // st.execute(sql1);//關(guān)閉連接conn.close();st.close();rs.close();} }3.DriverManager對(duì)象
3.1DriverManager對(duì)象簡(jiǎn)介
DriverManager是驅(qū)動(dòng)管理對(duì)象,有兩個(gè)功能,第一個(gè)功能是注冊(cè)驅(qū)動(dòng),第二個(gè)功能是獲取數(shù)據(jù)庫(kù)連接
3.2DriverManager注冊(cè)驅(qū)動(dòng)
我們查看DriverManager類發(fā)現(xiàn)它有這么一個(gè)方法
static void registerDriver(Driver driver):注冊(cè)與給定的驅(qū)動(dòng)程序DriverManager但是我們可以看到我們的注冊(cè)驅(qū)動(dòng)用到的是
String JDBCDriver ="com.mysql.jdbc.Driver";
Class.forName(JDBCDriver);
這樣的兩句代碼,那么好像和我們的DriverManager無(wú)關(guān)。
其實(shí)不是,我們寫(xiě)代碼使用的是Class.forName("com.mysql.jdbc.Driver")把Driver加載到JVM中,
類里面有靜態(tài)代碼塊自動(dòng)執(zhí)行
看到這樣的兩句代碼是不是就恍然大悟,原來(lái)在加載這個(gè)類的同時(shí)執(zhí)行了同同步代碼塊,就是在注冊(cè)驅(qū)動(dòng)
再看下面一張圖
我們可以看到這個(gè)jar包已經(jīng)包含了這個(gè)驅(qū)動(dòng)加載,如果我們沒(méi)有寫(xiě)注冊(cè)驅(qū)動(dòng),他也會(huì)自動(dòng)加載驅(qū)動(dòng)(也就是說(shuō)Mysql5之后的版本驅(qū)動(dòng)的jar包可以省略注冊(cè)驅(qū)動(dòng)的步驟)
3.2DriverManager獲取數(shù)據(jù)庫(kù)連接
方法:
public static Connection getConnection(String url,String user,String password)參數(shù):
*url:指定連接的路徑
*語(yǔ)法:jdbc:mysql://ip地址(域名):端口號(hào)/數(shù)據(jù)庫(kù)名
*例子:jdbc:mysql://localhost:3306/db3
*細(xì)節(jié):如果連接的是本機(jī)mysql服務(wù)器且端口號(hào)為3306,可以省略jdbc:mysql:///數(shù)據(jù)庫(kù)連接名
4.Connectioin對(duì)象
Connection:數(shù)據(jù)庫(kù)連接對(duì)象,它的功能有:
1.功能:
獲取執(zhí)行sql的對(duì)象
Statement createStatement()
PreparedStatement prepareStatement(String sql)
2.管理事務(wù):
開(kāi)啟事務(wù):setAutoCommit(boolean autoCommit):調(diào)用該方法設(shè)置參數(shù)為false,即開(kāi)啟事務(wù)
提交事務(wù):commit();
回滾事務(wù):rollback();
5.Statement對(duì)象
它的作用的執(zhí)行sql語(yǔ)句,對(duì)應(yīng)的方法有:
(1) boolean execute(String sql):可以執(zhí)行任意的sql ,不常用(因?yàn)樗嘤糜谔幚硐鄬?duì)復(fù)雜的sql語(yǔ)句)了解即可
(2) int executeUpdate(String sql):執(zhí)行DML(insert update delete) DDL(create alert drop)語(yǔ)句
返回值:影響的行數(shù),可以通過(guò)這個(gè)影響的行數(shù)判斷DML語(yǔ)句是否執(zhí)行成功
(3)ResultSet executeQuery(String sql): 執(zhí)行DQL語(yǔ)句
6.ResultSet對(duì)象
ResultSet對(duì)象:結(jié)果集對(duì)象,我們DQL查詢的結(jié)果都在這個(gè)對(duì)象里,它里邊的方法有:1 . next():游標(biāo)向下移動(dòng)一行(如下圖游標(biāo)默認(rèn)指向id所在行,所以我們需要此方法移動(dòng)游標(biāo))
2 .getXXX(參數(shù)):獲取數(shù)據(jù)
XXX代表數(shù)據(jù)類型 如:int getInt(); String getString();
$參數(shù):
1.int:代表列的編號(hào),從1開(kāi)始 如:getString(1);【對(duì)應(yīng)下圖id】
2.String代表的是列的名稱,如:getDouble(“balance”);
我們獲取結(jié)果集里邊的數(shù)據(jù),需要按照如圖的方式:
代碼模版
while(rs.next()){//6.2獲取數(shù)據(jù)int id=rs.getInt(1);//參數(shù)可以是數(shù)字代表列,可以直接是列名String name=rs.getString("name");double balance=rs.getDouble(3);System.out.println(id+"---"+name+"---"+balance); }我舉個(gè)例子,下表打印出來(lái)
7.JDBC工具類
剛才我舉的例子可以看出來(lái)每一次使用JDBC就會(huì)有很多重復(fù)的代碼塊(注冊(cè)驅(qū)動(dòng)釋放資源都是重復(fù)的代碼),JDBC的工具類就是把那么多重復(fù)的代碼塊封裝起來(lái)變成一個(gè)新的類,每次使用的時(shí)候就調(diào)用這類里的個(gè)方法,那么當(dāng)我們多次使用JDBC的時(shí)候就會(huì)簡(jiǎn)便的多,我們把上面的例子拿過(guò)來(lái),然后進(jìn)行改進(jìn)
我們知道獲取連接的時(shí)候就是上面例子的這段代碼:
conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/student","root","2332402105");,現(xiàn)在們把這段代碼包裝成一個(gè)方法,我們的要求是,方法不允許有參數(shù),還要保證方法的通用性,這時(shí)候我們就需要用到我們的配置文件了,里邊記錄我們獲取連接的三個(gè)參數(shù),然后把釋放資源也包裝成一個(gè)方法。然后再把我們釋放資源封裝成一個(gè)方法,就有了如下工具類
配置文件里有:
那么每當(dāng)我們使用JDBC的時(shí)獲取連接和釋放資源都可以使用這個(gè)工具類,配置文件的三個(gè)參數(shù)根據(jù)連接的數(shù)據(jù)庫(kù)不同適當(dāng)更改,就會(huì)方便很多
8.PreparedStatement類
8.1登錄案例
我們做一個(gè)登錄案例試試:
我們的student數(shù)據(jù)庫(kù)里邊有一個(gè)表user,然后利用這一個(gè)表做一個(gè)登錄的案例:
user表:
那么我們按照上圖的用戶名和密碼進(jìn)行登錄,代碼如下
運(yùn)行結(jié)果:
那么其實(shí)這里有一個(gè)bug,比如下面的語(yǔ)句查出了所有的用戶
我們舉一個(gè)例子:
我們的表里明明沒(méi)有這一個(gè)user信息為啥會(huì)登錄成功呢,那么這里就牽扯到我們的SQL注入問(wèn)題
SQL注入:在拼接sql語(yǔ)句時(shí)有一些sql的特殊關(guān)鍵字參與字符串的拼接,會(huì)造成安全性的問(wèn)題
按照上圖輸入我們的實(shí)際的查詢語(yǔ)句是:
當(dāng)然可以查到用戶,而且是相當(dāng)于查詢所有的用戶,因?yàn)橛幸粋€(gè)or和一個(gè)恒等式
這時(shí)候就要用到我們的PreparedStatement類,父類是Statement
1.Statement:執(zhí)行靜態(tài)的sql語(yǔ)句,就是直接把我們輸入的數(shù)據(jù)偷換掉sql語(yǔ)句重的username和password,
2.PreparedStatement:首先預(yù)編譯sql語(yǔ)句,參數(shù)使用占位符?替換
和Statement用法有所不同的是
- sql參數(shù)使用占位符如:"select * from user where name=? and password=?"
- 需要用PrepareStatement對(duì)象的方法給占位符賦值
- 在執(zhí)行sql的時(shí)候不需要傳遞sql語(yǔ)句了,因?yàn)樵讷@取PreparedStatement對(duì)象時(shí)候需要傳遞一個(gè)sql語(yǔ)句用于預(yù)編譯
那么我們按照描述修改例子的代碼:
package Login;import java.sql.*; import java.util.Scanner;public class login {public boolean LoGin(String username,String password){if(username==null||password==null)return false;Connection conn=null;PreparedStatement pstmt=null;ResultSet res=null;try{Class.forName("com.mysql.jdbc.Driver");conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/student","root","2332402105");//定義預(yù)編譯sql語(yǔ)句strString str="select * from user where name=? and password=?" ;//獲取 PreparedStatement對(duì)象并且傳遞預(yù)編譯sql語(yǔ)句pstmt=conn.prepareStatement(str);//set方法給占位符賦值,第一個(gè)參數(shù)1代表第一個(gè)占位符,2代表第二個(gè)占位符,第二個(gè)參數(shù)是賦的值pstmt.setString(1,username);pstmt.setString(2,password);res = pstmt.executeQuery();return res.next();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}finally {if(conn!=null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}if(pstmt!=null){try {pstmt.close();} catch (SQLException e) {e.printStackTrace();}} if(res!=null){try {res.close();} catch (SQLException e) {e.printStackTrace();}}}return false;}public static void main(String[] args) {Scanner p=new Scanner(System.in);System.out.println("請(qǐng)輸入用戶名:");String username=p.next();System.out.println("請(qǐng)輸入密碼:");String password=p.next();boolean bool=new login().LoGin(username,password);if(bool){System.out.println("登錄成功");}else{System.out.println("登錄失敗");}} }
成功解決sql注入問(wèn)題
9.JDBC管理事務(wù)
在獲取到Connection對(duì)象后,用Connection對(duì)象方法setAutoCommit(boolean autoCommit):參數(shù)為false開(kāi)啟事務(wù)
然后整個(gè)語(yǔ)句結(jié)束后使用Connection對(duì)象的commit()方法對(duì)事務(wù)進(jìn)行提交,我們還可以使用Connection對(duì)象的rollback()方法對(duì)事務(wù)進(jìn)行回滾
總結(jié)
以上是生活随笔為你收集整理的JDBC有这一篇就够了(万字JDBC附代码详解)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 筛选法求素数
- 下一篇: 详解图的各种令人心慌的概念和四种图的存储