原生JDBC
JDBC
Java DataBase Connectivity,java數據庫連接,是一種用於執行SQL語句的Java API。
JDBC是Java訪問數據庫的標準規範,可以為不同的關系型數據庫提供統一訪問,它由一組用Java語言編寫的接口和類組成。
驅動
JDBC需要連接驅動,驅動是兩個設備要進行通信,滿足一定通信數據格式,數據格式由設備提供商規定,設備提供商為設備提供驅動軟件,通過軟件可以與該設備進行通信。
JDBC規範(掌握四個核心對象)
DriverManager:用於註冊驅動
Connection: 表示與數據庫創建的連接
Statement: 操作數據庫sql語句的對象
ResultSet: 結果集或一張虛擬表
使用JDBC技術,通過mysql提供的驅動程序,操作數據庫實現步驟:
1.註冊驅動
告知JVM我們使用的是什麽驅動程序(mysql,oracle....)
DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建議使用
原因有2個:
>導致驅動被註冊2次。
>強烈依賴數據庫的驅動jar
解決辦法:
Class.forName("com.mysql.jdbc.Driver");
2.獲取數據庫的連接
數據庫是TCP程序服務器,連接服務器(通過3次握手)
就相當於建立了一條java程序通往數據庫服務器的連接通路
static Connection getConnection(String url, String user, String password)
試圖建立到給定數據庫 URL 的連接。
參數說明:url 需要連接數據庫的位置(網址) user用戶名 password 密碼
例如:getConnection("jdbc:mysql://localhost:3306/day06", "root", "root");
URL:SUN公司與數據庫廠商之間的一種協議。
jdbc:mysql://localhost:3306/day06
協議子協議 IP :端口號數據庫
mysql: jdbc:mysql://localhost:3306/day04或者jdbc:mysql:///day14(默認本機連接)
oracle數據庫: jdbc:oracle:thin:@localhost:1521:sid
3.獲取執行者對象
執行SQL語句的對象,作用就是執行SQL
接口的實現在數據庫驅動中。所有與數據庫交互都是基於連接對象的。
Statement createStatement(); //創建操作sql語句的對象
4.執行SQL語句,獲取結果集
使用執行者對象執行SQL語句
獲取SQL語句的結果集(增刪改:整數,執行有效行數 查詢:返回的就是一個結果集)
常用方法:
? int executeUpdate(String sql); --執行insert update delete語句.
? ResultSet executeQuery(String sql); --執行select語句.
? boolean execute(String sql); --僅當執行select並且有結果時才返回true,執行其他的語句返回false.
5.處理結果集
ResultSet實際上就是一張二維的表格,我們可以調用其boolean next()方法指向某行記錄,當第一次調用next()方法時,便指向第一行記錄的位置,這時就可以使用ResultSet提供的getXXX(int col)方法(與索引從0開始不同個,列從1開始)來獲取指定列的數據:
rs.next();//指向第一行
rs.getInt(1);//獲取第一行第一列的數據
常用方法:
? Object getObject(int index) / Object getObject(String name) 獲得任意對象
? String getString(int index)/ String getString(String name) 獲得字符串
? int getInt(int index)/int getInt(String name) 獲得整形
? double getDouble(int index)/ double getDouble(String name) 獲得雙精度浮點型
6.釋放資源
與IO流一樣,使用後的東西都需要關閉!關閉的順序是先得到的後關閉,後得到的先關閉。
使用JDBC對數據庫進行增刪改查代碼演示:
1 public static void main(String[] args) throws Exception { 2 //1.註冊驅動 3 Class.forName("com.mysql.jdbc.Driver"); 4 //2.獲取數據庫連接 5 String url = "jdbc:mysql://localhost:3306/mybase4"; 6 String user = "root"; 7 String password = "root"; 8 Connection conn = DriverManager.getConnection(url, user, password);9 //3.獲取執行者對象 10 Statement stat = conn.createStatement(); 11 //調用更新數據的方法 12 //update(stat); 13 //調用刪除數據的方法 14 //delete(stat); 15 //調用增加數據的方法 16 //insert(stat); 17 //調用查詢數據的方法 18 select(stat); 19 //6.釋放資源 20 stat.close(); 21 conn.close(); 22 } 23 24 /* 25 * 使用JDBC技術,查詢數據庫中表的數據 26 */ 27 private static void select(Statement stat) throws Exception { 28 //拼接sql語句 29 String sql = "SELECT * FROM category"; 30 /* 31 * 4.執行sql語句 32 * 使用Statement中的方法 33 * ResultSet executeQuery(String sql) 執行給定的 SQL 語句,該語句返回單個 ResultSet 對象。 34 * 返回值ResultSet標準接口的實現類對象,實現類對象由mysql驅動提供,可以使用ResultSet接口接收 35 */ 36 ResultSet rs = stat.executeQuery(sql); 37 System.out.println(rs);//[email protected] 38 /* 39 * 5.處理結果 40 * ResultSet中有一個方法 41 * boolean next() 將光標從當前位置向前移一行。 42 * 如果新的當前行有效,則返回 true;如果不存在下一行,則返回 false 43 * 如果有結果集返回true,若果沒有結果集返回false 44 * 相當於叠代器中的hasNext方法 45 */ 46 while(rs.next()){ 47 /* 48 * next返回true,有結果集 49 * 取出結果集 50 * 使用ResultSet中的方法getXXX(參數); 51 * 參數: 52 * int columnIndex:列所在的索引,從1開始 53 * String columnLabel:列名 54 * 註意: 55 * 如果使用getInt,getDouble指定數據類型的方法,返回值就是對應的數據類型 56 * 如果使用getObject方法返回值是object類型(只是打印可用) 57 * 如果使用getString方法返回值是String類型 58 */ 59 /*int i1 = rs.getInt(1); 60 String s2 = rs.getString(2); 61 System.out.println(i1+"\t"+s2);*/ 62 63 //System.out.println(rs.getObject(1)+"\t"+rs.getObject(2)); 64 System.out.println(rs.getObject("cid")+"\t"+rs.getObject("cname")); 65 //5.釋放資源 66 rs.close(); 67 } 68 } 69 70 /* 71 * 使用JDBC技術,對數據庫中的表數據進行增加 72 */ 73 private static void insert(Statement stat) throws SQLException { 74 //拼接sql語句 75 String sql = "INSERT INTO category(cname) VALUES(‘玩具‘)"; 76 //4.執行sql語句 77 int row = stat.executeUpdate(sql); 78 //5.處理結果 79 if(row>0){ 80 System.out.println("增加數據成功!"); 81 }else{ 82 System.out.println("增加數據失敗!"); 83 } 84 85 } 86 87 /* 88 * 使用JDBC技術,對數據庫中的表數據進行刪除 89 */ 90 private static void delete(Statement stat) throws Exception { 91 //拼接sql語句 92 String sql = "DELETE FROM category WHERE cid=5"; 93 //4.執行sql語句 94 int row = stat.executeUpdate(sql); 95 //5.處理結果 96 if(row>0){ 97 System.out.println("刪除數據成功!"); 98 }else{ 99 System.out.println("刪除數據失敗!"); 100 } 101 } 102 103 /* 104 * 使用JDBC技術,對數據庫中的表數據進行更新 105 */ 106 private static void update(Statement stat) throws Exception { 107 //拼接sql語句 108 String sql = "UPDATE category SET cname=‘鞋帽‘ WHERE cid=6"; 109 //4.執行sql語句 110 int row = stat.executeUpdate(sql); 111 //5.處理結果 112 if(row>0){ 113 System.out.println("更新數據成功!"); 114 }else{ 115 System.out.println("更新數據失敗!"); 116 } 117 }
1 JDBC工具類 2 “獲得數據庫連接”操作,將在以後的增刪改查所有功能中都存在,可以封裝工具類JDBCUtils。提供獲取連接對象的方法,從而達到代碼的重復利用。 3 代碼演示: 4 public class JDBCUtils { 5 6 //私有構造方法,防止外界創建對象調用方法 7 private JDBCUtils() { 8 } 9 10 //定義Connectionn變量 11 private static Connection conn; 12 13 //保證代碼只執行一次,可以放入靜態代碼塊中 14 static{ 15 try { 16 //註冊驅動 17 Class.forName("com.mysql.jdbc.Driver"); 18 //獲取連接 19 String url="jdbc:mysql://127.0.0.1:3306/mybase4"; 20 String user="root"; 21 String password = "root"; 22 conn = DriverManager.getConnection(url, user, password); 23 } catch (Exception e) { 24 //註意,如果連接數據庫失敗,停止程序 25 throw new RuntimeException(e+"連接數據庫失敗"); 26 } 27 } 28 29 //創建一個靜態方法,獲取數據庫連接對象,並返回 30 public static Connection getConnection(){ 31 return conn; 32 } 33 34 /* 35 * 創建一個靜態方法,對資源進行釋放 36 * ResultSet rs 37 * Statement stat 38 * Connection conn 39 */ 40 public static void close(ResultSet rs,Statement stat,Connection conn){ 41 try { 42 if(rs!=null){ 43 rs.close(); 44 } 45 } catch (SQLException e) { 46 e.printStackTrace(); 47 } 48 try { 49 if(stat!=null){ 50 stat.close(); 51 } 52 } catch (SQLException e) { 53 e.printStackTrace(); 54 } 55 try { 56 if(conn!=null){ 57 conn.close(); 58 } 59 } catch (SQLException e) { 60 e.printStackTrace(); 61 } 62 } 63 }
sql註入問題
SQL註入:用戶輸入的內容作為了SQL語句語法的一部分,改變了原有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:預編譯對象,是Statement對象的子類。
特點:
性能高
會把sql語句先編譯
能過濾掉用戶輸入的關鍵字。
PreparedStatement預處理對象,處理的每條sql語句中所有的實際參數,都必須使用占位符?替換。
String sql = "select * from user where username = ? and password = ?";
PreparedStatement使用,需要通過以下3步驟完成:
1.PreparedStatement預處理對象代碼:
獲得預處理對象,需要提供已經使用占位符處理後的SQL語句
PreparedStatement psmt = conn.prepareStatement(sql)
2.設置實際參數
void setXxx(int index, Xxx xx) 將指定參數設置指定類型的值
參數1:index 實際參數序列號,從1開始。
參數2:xxx 實際參數值,xxx表示具體的類型。
例如:
setString(2, "1234") 把SQL語句中第2個位置的占位符?替換成實際參數 "1234"
3.執行SQL語句:
int executeUpdate(); --執行insert update delete語句.
ResultSet executeQuery(); --執行select語句.
boolean execute(); --執行select返回true 執行其他的語句返回false.
原生JDBC