JDBC(Java Data Base Connectivity,Java數據庫鏈接)是一種用於執行SQL語句的Java API,它是一種用Java語言編寫的類與接口,是Java訪問數據庫的標準規範。java
JDBC須要鏈接驅動,驅動是兩個設備要進行通訊,知足必定通訊數據格式,數據格式由設備的提供商規定,設備提供商爲設備提供驅動軟件,通訊軟件能夠與該設備進行通訊。mysql
JDBC原理程序員
JDBC是接口,驅動是接口的實現,沒有驅動將沒法完成數據庫的鏈接,從而不能操做數據庫!每一個數據庫廠商都須要提供本身的驅動,用來鏈接本身公司的數據庫,也就是說驅動通常都由數據庫生成廠商提供,本身只要會用就行。sql
JDBC開發步驟數據庫
一、註冊驅動oracle
告知JVM使用的是哪一類數據庫的驅動ui
二、得到鏈接url
使用JDBC中的類,完成對MySQL數據庫的鏈接spa
三、得到語句執行平臺對象
經過鏈接對象獲取對SQL語句的執行者對象
四、執行SQL語句
使用執行者對象,向數據庫執行SQL語句
獲取到數據庫的執行後的結果
五、返回結果集
六、釋放資源(先開的後關)
調用一堆close()方法
導入驅動jar包
建立lib目錄,用於存放當前項目須要的全部jar包
選擇jar包,右鍵執行build path / Add to Build Path
開發第一步:註冊驅動
使用Class.forName("com.mysql.jdbc.Driver"); 加載一個使用字符串描述的驅動類。
使用Class.forName()將類加載到內存,該類的靜態代碼塊將自動執行。
查詢com.mysql.jdbc.Driver源碼,發現Driver類「主動」將本身進行註冊 因此此時直接用Class.forName()直接將類加載到內存中,而不在從新註冊 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!"); } } …… }
開發第二步:得到鏈接
獲取鏈接的方法是DriverManager的getConnection(url,username,password)方法
url="jdbc:mysql://主機IP:端口號/數據庫名"
例如:String url = "jdbc:mysql://localhost:3306/demo_jdbc?characterEncoding=utf-8";
String url = "jdbc:mysql://localhost:3306/demo_jdbc?characterEncoding=utf-8";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
開發第三步:獲取語句執行平臺
Statement sta = conn.createStatement();
開發第四步:執行sql語句
String sql="某sql語句";
int row=sta.executeUpdate(sql); //executeUpdate 返回SQL語句執行後的行數
開發第五步:返回結果集
System.out.println(row);
開發第六步:釋放資源(先開的後關)
例如:sta.close();
conn.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預處理對象
String sql="某SQL執行語句";
PreparedStatement pst =conn.prepareStatement(sql);
執行SQL語句
int executeUpdate(); --執行insert update delete語句.
ResultSet executeQuery(); --執行select語句.
boolean execute(); --執行select返回true 執行其餘的語句返回false.
設置實際參數
void setXxx(int index, Xxx xx) 將指定參數設置爲給定Java的xx值。在將此值發送到數據庫時,驅動程序將它轉換成一個 SQL Xxx類型值。
預處理對象的executeUpdate方法
插入insert public void demo01() throws Exception { // 1註冊驅動 Class.forName("com.mysql.jdbc.Driver"); // 2獲取鏈接 Connection conn = DriverManager.getConnection ("jdbc:mysql://localhost:3306/mydb", "username", "password"); // 3得到預處理對象 String sql = "insert into sort(sname) values(?)"; PreparedStatement pst = conn.prepareStatement(sql); // 4 SQL語句佔位符設置實際參數 pst.setString(1, "奢侈品"); // 5執行SQL語句 int line =pst.executeUpdate(); System.out.println("新添加記錄數:" + line); // 6釋放資源 pst.close(); conn.close(); }
更新update public void demo02() throws Exception { // 1註冊驅動 Class.forName("com.mysql.jdbc.Driver"); // 2獲取鏈接 Connection conn = DriverManager.getConnection ("jdbc:mysql://localhost:3306/mydb", "username", "password"); // 3得到預處理對象中 String sql = "update sort set sname=? where sid=?"; PreparedStatement pst = conn.prepareStatement(sql); // 4 SQL語句佔位符設置實際參數 pst.setString(1, "數碼產品"); pst.setInt(2, 1); // 5執行SQL語句 int line = pst.executeUpdate(); System.out.println("更新記錄數:" + line); // 6釋放資源 pst.close(); conn.close(); }
刪除delete public void demo03() throws Exception { // 1註冊驅動 Class.forName("com.mysql.jdbc.Driver"); // 2獲取鏈接 Connection conn = DriverManager.getConnection ("jdbc:mysql://localhost:3306/mydb", "username", "password"); // 3得到預處理對象 String sql = "delete from sort where sid=?"; PreparedStatement pst = conn.prepareStatement(sql); // 4 SQL語句佔位符設置實際參數 pst.setInt(1, 1); // 5執行SQL語句 int line = pst.executeUpdate(); System.out.println("刪除記錄數:" + line); // 6釋放資源 pst.close(); conn.close(); }
預處理對象executeQuery方法
實現查詢分類表全部記錄 public void demo04() throws Exception { // 1註冊驅動 Class.forName("com.mysql.jdbc.Driver"); // 2獲取鏈接 Connection conn = DriverManager.getConnection ("jdbc:mysql://localhost:3306/mydb", "username", "password"); // 3得到預處理對象 String sql = "select * from sort"; PreparedStatement pst = conn.prepareStatement(sql); // 4 SQL語句佔位符設置實際參數 // 5執行SQL語句 ResultSet rs = pst.executeQuery(); // 6處理結果集(遍歷結果集合) while( rs.next() ){ //獲取當前行的分類ID String sid = rs.getString("sid");//方法參數爲數據庫表中的列名 //獲取當前行的分類名稱 String sname = rs.getString("sname"); //顯示數據 System.out.println(sid+"-----"+sname); } // 7釋放資源 rs.close(); pst.close(); conn.close(); }
在作數據庫鏈接時咱們會發現一些重複性的代碼好比:註冊驅動、得到鏈接,釋放資源,因此將其封裝成一個方法以便往後去用。
package com.oracle.demo1; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class DButil { private DButil(){} static Connection conn; static{ try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/demo_jdbc?characterEncoding=utf-8"; String username = "root"; String password = "123456"; conn = DriverManager.getConnection(url, username, password); } catch (Exception ex) { throw new RuntimeException(ex+"數據庫鏈接失敗"); } } public static Connection getConn(){ return conn; } public static void close(Statement sta,Connection conn){ if(sta!=null){ try{ sta.close(); }catch(SQLException ex){} } if(conn!=null){ try{ conn.close(); }catch(SQLException ex){} } } public static void close(ResultSet rs,Statement sta,Connection conn){ if(rs!=null){ try{ rs.close(); }catch(SQLException ex){} } if(sta!=null){ try{ sta.close(); }catch(SQLException ex){} } if(conn!=null){ try{ conn.close(); }catch(SQLException ex){} } } }
總結:
Statement 接口提供了三種執行 SQL 語句的方法:executeQuery、executeUpdate 和 execute。
使用哪個方法由 SQL 語句所產生的內容決定。
方法executeQuery
用於產生單個結果集的語句,例如 SELECT 語句。
被使用最多的執行 SQL 語句的方法是 executeQuery。這個方法被用來執行 SELECT 語句,它幾乎是使用最多的 SQL 語句。
方法executeUpdate
用於執行 INSERT、UPDATE 或 DELETE 語句以及 SQL DDL(數據定義語言)語句,
例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE 語句的效果是修改表中零行或多行中的一列或多列。
executeUpdate 的返回值是一個整數,指示受影響的行數(即更新計數)。
對於 CREATE TABLE 或 DROP TABLE 等不操做行的語句,executeUpdate 的返回值總爲零。
使用executeUpdate方法是由於在 createTableCoffees 中的 SQL 語句是 DDL (數據定義語言)語句。
建立表,改變表,刪除表都是 DDL 語句的例子,要用 executeUpdate 方法來執行。你也能夠從它的名字裏看出,方法 executeUpdate 也被用於執行更新表 SQL 語句。實際上,相對於建立表來講,executeUpdate 用於更新表的時間更多,由於表只須要建立一次,但常常被更新。
方法execute: 用於執行返回多個結果集、多個更新計數或兩者組合的語句。由於多數程序員不會須要該高級功能