一、概述
JDBC(Java Data Base Connectivity,java數據庫連接)是一種用於執行SQL語句的Java API,可以為多種關系數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。是Java訪問數據庫的標准規范
JDBC提供了一種基准,據此可以構建更高級的工具和接口,使數據庫開發人員能夠編寫數據庫應用程序。
JDBC需要連接驅動,驅動是兩個設備要進行通信,滿足一定通信數據格式,數據格式由設備提供商規定,設備提供商為設備提供驅動軟件,通過軟件可以與該設備進行通信。
今天我們使用的是mysql的驅動mysql-connector-java-5.1.39-bin.jar
二、JDBC原理
Java提供訪問數據庫規范稱為JDBC,而生產廠商提供規范的實現類稱為驅動。
JDBC是接口,驅動是接口的實現,沒有驅動將無法完成數據庫連接,從而不能操作數據庫!每個數據庫廠商都需要提供自己的驅動,用來連接自己公司的數據庫,也就是說驅動一般都由數據庫生成廠商提供。
三、JDBC開發步驟 重點,必須記住
1.注冊驅動
用來告訴JVM使用的是哪個生產廠商的驅動
2.獲得鏈接,鏈接數據庫
使用JDBC中的類,完成對MySQL數據庫的鏈接
3.獲得語句執行平台
通過連接對象獲取對SQL語句的執行對象
4.執行SQL語句
使用執行對象對數據庫執行SQL語句
獲取執行結果
5.處理結果
處理結果集,(insert、update、delete無需處理)
6.釋放資源
調用一堆 close()方法,將調用的對象彈棧
詳細步驟:
1.導入驅動jar包
創建lib文件夾,存放所需要的所有jar包。
選擇jar包,右鍵選擇 bulid path 再選擇 Add to bulid path
如圖:
2.注冊驅動
代碼:class.forName("com.mysql.jdbc.Dirver");
JDBC規范定義驅動接口:java.sql.Driver,MySql驅動包提供了實現類:com.mysql.jdbc.Driver
3.獲得鏈接
代碼:Connection conn=DiverManager.getConnection("jdbc:Mysql://localhost:3306/goods,'root','123456'");
獲取連接需要方法 DriverManager.getConnection(url,username,password),三個參數分別表示,url 需要連接數據庫的位置(網址) user用戶名 password 密
url比較復雜,下面是mysql的url:
jdbc:mysql://localhost:3306/mydb
JDBC規定url的格式由三部分組成,每個部分中間使用冒號分隔。
第一部分是jdbc,這是固定的;
第二部分是數據庫名稱,那么連接mysql數據庫,第二部分當然是mysql了;
第三部分是由數據庫廠商規定的,我們需要了解每個數據庫廠商的要求,mysql的第三部分分別由數據庫服務器的IP地址(localhost)、端口號(3306),以及DATABASE名稱(mydb)組成。
4.獲得SQL語句執政平台
代碼:String sql="某sql語句";
獲取Statement語句執行平台:Statement stmt=con.createStatement();
常用方法:
(1)int executeUpdate(String sql); ------ 執行intert 、update、delete(增刪改操作)語句
(2)ResultSet executeQuery(String sql);-------執行select(查詢操作) 語句
(3) boolean execute(String sql); --執行select返回true 執行其他的語句返回false.
5.處理結果集(執行insert、update、delete無需處理)
ResultSet實際上就是一張二維的表格,我們可以調用其boolean next()方法指向某行記錄,當第一次調用next()方法時,便指向第一行記錄的位置,
這時就可以使用ResultSet提供的getXXX(int col)方法(與索引從0開始不同個,列從1開始)來獲取指定列的數據:
代碼:rs.next();//指向第一行
rs.getInt(1);//獲取第一行第一列的數據
常用方法:
(1)Object getObject(int index) / Object getObject(String name) 獲得任意對象
(2) String getString(int index) / Object getObject(String name) 獲得字符串
(3) int getInt(int index) / Object getObject(String name) 獲得整形
(4) double getDouble(int index) / Object getObject(String name) 獲得雙精度浮點型
6.釋放資源
與IO流一樣,使用后的東西都需要關閉!關閉的順序是先得到的后關閉,后得到的先關閉。
實例代碼:
rs.close();
stmt.close();
con.close();
四、SQL注入問題
假設有登錄案例SQL語句如下:
SELECT * FROM 用戶表 WHERE NAME = 用戶輸入的用戶名 AND PASSWORD = 用戶輸的密碼;
此時,當用戶輸入正確的賬號與密碼后,查詢到了信息則讓用戶登錄。但是當用戶輸入的賬號為XXX 密碼為:XXX’ OR ‘a’=’a時,則真正執行的代碼變為:
SELECT * FROM 用戶表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’ OR ’a’=’a’;
此時,上述查詢語句時永遠可以查詢出結果的。那么用戶就直接登錄成功了,顯然我們不希望看到這樣的結果,這便是SQL注入問題。
為此,我們使用PreparedStatement來解決對應的問題。
五、預處理對象
使用PreparedStatement預處理對象時,建議每條sql語句所有的實際參數,都使用逗號分隔。
String sql = "insert into sort(sid,sname) values(?,?)";; PreparedStatement預處理對象代碼: PreparedStatement psmt = conn.prepareStatement(sql);
常用方法:
1. 執行SQL語句:
int executeUpdate(); --執行insert update delete語句.
ResultSet executeQuery(); --執行select語句.
boolean execute(); --執行select返回true 執行其他的語句返回false.
2.設置實際參數
void setXxx(int index, Xxx xx) 將指定參數設置為給定Java的xx
值。在將此值發送到數據庫時,驅動程序將它轉換成一個 SQL Xxx
類型
值。
例如:
setString(2, "家用電器") 把SQL語句中第2個位置的占位符? 替換成實際參數 "家用電器"
實例代碼:
package com.oracle.Demo01; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import com.mysql.jdbc.Driver; public class demo01 { public static void main(String[] args) throws SQLException, ClassNotFoundException { // TODO Auto-generated method stub // 1. 注冊驅動. // 告知JVM使用的是哪一個數據庫的驅動 //DriverManager.registerDriver(new Driver()); // 把com.mysql.jdbc.Driver這個實現類直接扔到內存里 // 扔到內存之后調用static靜態代碼塊 // 靜態代碼塊中注冊驅動 Class.forName("com.mysql.jdbc.Driver"); //com.mysql.jdbc為驅動所在包 // 2. 獲得連接對象. // 使用JDBC中的類,完成對MySQL數據庫的連接 //jdbc:mysql://localhost:3306/數據庫名 String url="jdbc:mysql://localhost:3306/goods?characterEncoding=utf-8"; String username="root"; String password="123456"; Connection conn=DriverManager.getConnection(url, username, password); // 3. 獲得語句執行平台 // 通過連接對象獲取對SQL語句的執行者對象 Statement sta=conn.createStatement(); //接收一定要用java里面的 導包導SQL里的 // 4. 執行sql語句 // 使用執行者對象,向數據庫執行SQL語句 // 獲取到數據庫的執行后的結果
//添加 String sql="insert into sort(sname,sdesc) value('電子設備','都是騙男人的')"; int row=sta.executeUpdate(sql); System.out.println(row); //修改 String sql="update sort set sname='玩具' where sid='1'"; int row=sta.executeUpdate(sql); System.out.println(row); //查詢 String sql="select * from sort"; //刪除 String sql="delete from sort where sid='1'"; // 5. 處理結果 (僅用於查詢) ResultSet rs=sta.executeQuery(sql); while(rs.next()){
System.out.println(rs.getInt("sid")+"..."+rs.getString("sname")+"..."+rs.getString("sdesc")); } // 6. 釋放資源. (先開的后關) // 調用一堆close()方法 關閉對象 rs.close(); sta.close(); conn.close(); } }
封裝JDBK方法:
package com.oracle.Demo01; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCUtils {
//提供獲取連接的方法
private static Connection conn=null; static{ try { Class.forName("com.mysql.jdbc.Driver"); String url="jdbc:mysql://localhost:3306/goods?characterEncoding=utf-8"; String username="root"; String password="123456"; conn=DriverManager.getConnection(url,username,password); } catch (Exception e) { // TODO Auto-generated catch block throw new RuntimeException(e+"數據庫連接失敗"); } } //獲取數據庫連接對象 public static Connection getConnection(){ return conn; } //關閉數據庫的方法 public static void close(ResultSet rs,Statement sta,Connection conn){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(sta!=null){ try { sta.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void close(Statement sta,Connection conn){ if(sta!=null){ try { sta.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
Test類:
package com.oracle.Demo01; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class Test { public static void main(String[] args) throws SQLException { // TODO Auto-generated method stub Connection conn=JDBCUtils.getConnection(); String sql="insert into user(username,password) value(?,?)"; PreparedStatement pst=conn.prepareStatement(sql); pst.setString(1, "李四"); pst.setString(2, "123456789"); int row=pst.executeUpdate(); System.out.println(row); JDBCUtils.close(pst, conn); } }
常用方法: