1.什么是JDBC -1.JDBC(Java Database Connection)為Java開發(fā)者使用數(shù)據(jù)庫提供了統(tǒng)一的編程接口,它由一組Java類和接口組成。是Java程序與數(shù)據(jù)庫通信的標準API。 JDBC API使得開發(fā)人員可以使用純Java的方式來連接數(shù) 據(jù)庫,并執(zhí)行操作。 -2.sun公司由于不知道各個主流商用數(shù)據(jù)庫的程序代碼,因此無法自己寫代碼連接各個數(shù)據(jù)庫,因此,sun公司自己提供了一套API,只要數(shù)據(jù)庫想要和Java連接的, 數(shù)據(jù)庫廠商必須自己實現(xiàn)JDBC這套接口。而數(shù)據(jù)庫廠商的JDBC實現(xiàn),我們就叫它此數(shù)據(jù)庫的驅(qū)動。 2.JDBC訪問數(shù)據(jù)庫流程 1.加載JDBC驅(qū)動程序 2.建立與數(shù)據(jù)庫的連接 3.發(fā)送SQL語句 4.得到SQL執(zhí)行結(jié)果 3.Java程序和數(shù)據(jù)庫連接的時候,其實就是Socket連接。 4.JDBC常用接口 Driver接口 - Driver接口由數(shù)據(jù)庫廠家提供,對于Java開發(fā)者而言,只需要使用Driver接口就可以了。 - 在編程中要連接數(shù)據(jù)庫,必須先裝載特定廠商的數(shù)據(jù)庫驅(qū)動程序。不同的數(shù)據(jù)庫有不同的裝載方法。 - 驅(qū)動:就是各個廠商實現(xiàn)Sun公司提出的JDBC接口。即對Connection等接口的實現(xiàn)類的jar文件。 - 裝載mysql驅(qū)動:Class.forName("com.mysql.jdbc.Driver"); - 裝載oracle驅(qū)動:Class.forName("com.jdbc.driver.OracleDriver"); DriverManager接口 - DriverManager接口是JDBC的管理層,作用于用戶和驅(qū)動程序之間。 - DriverManager跟蹤可用的驅(qū)動程序,并在數(shù)據(jù)庫和相應(yīng)的驅(qū)動之間建立連接。 Connection接口 - Connection與特定數(shù)據(jù)庫的連接(會話),在連接上下文中執(zhí)行SQL語句并返回結(jié)果。 - DriverManager的getConnection()方法建立在JDBC URL中定義的數(shù)據(jù)庫Connection連接上 -Mysql Connection con = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password"); -Oracle Connection con = DriverManager.getConnection("jdbc:oracle:thin@host:port/database", "user", "password"); Statement接口 - 用于執(zhí)行靜態(tài)SQL語句并返回它所生成結(jié)果的對象。 - 三種Statement類: - Statement: 由createStatement創(chuàng)建,用于發(fā)送簡單的SQL語句(不帶參數(shù)) - PreparedStatement: - 繼承自Statement接口,有preparedStatement創(chuàng)建,用于發(fā)送含有一個或者多個輸入?yún)?shù)的SQL語句。PreparedStatement對象 比Statement對象效率更高,并且是防止SQL注入。我們一般都使用PreparedStatement。 - CallableStatement: - 繼承自preparedStatement。由方法prePareCall創(chuàng)建,用于調(diào)用存儲過程。 - 常用的Statement方法 - execute():運行語句,返回是否有結(jié)果集。 - executeQuery():運行select語句,返回ResultSet結(jié)果節(jié) - executeUpdate():運行insert/update/delete操作,返回更新的行數(shù)。 - 例子:
package com.yf.jdbc.test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * 測試執(zhí)行SQL語句和SQL注入問題 * @author yangf * */ public class Demo02 { public static void main(String[] args) { try { // 加載數(shù)據(jù)庫驅(qū)動 Class.forName("com.mysql.jdbc.Driver"); // 獲得connection對象 建立與數(shù)據(jù)庫連接 /* * 連接對象內(nèi)部其實包含了Socket對象,是一個遠程連接。比較耗時!這是Connection對象管理的一個要點。 * 后面通過連接池來做 */ Connection con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/testjdbc", "root", "123456"); Statement stmt = con.createStatement(); String sql = "insert into t_user (username,pwd,regTime) values ('yyy',123123,now())"; stmt.execute(sql); String sql1 = "delete from t_user where id = 4"; stmt.execute(sql1); // 測試SQL注入 // 由于是外部傳入?yún)?shù),所以可以任意修改DB,造成SQL注入,所以我們不適用Statement String id = "5 or 1 = 1"; String sql2 = "delete from t_user where id = " + id; stmt.execute(sql2); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } } package com.yf.jdbc.test; import java.sql.Connection; import java.sql.Date; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; /** * 測試PreparedStatement的基本用法 * @author yangf * */ public class Demo03 { public static void main(String[] args) { try { // 加載數(shù)據(jù)庫驅(qū)動 Class.forName("com.mysql.jdbc.Driver"); // 獲得connection對象 建立與數(shù)據(jù)庫連接 Connection con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/testjdbc", "root", "123456"); String sql = "insert into t_user (username,pwd,regTime) values (?,?,?)"; PreparedStatement ps = con.prepareStatement(sql); ps.setString(1, "yangf"); ps.setInt(2, 888888); ps.setDate(3, new Date(System.currentTimeMillis())); ps.execute(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } }
ResultSet接口 - Statement執(zhí)行SQL語句時返回Result結(jié)果集。 - ResultSet提供的檢索不同類型字段的方法,常用的有: - getString():獲得在數(shù)據(jù)庫里是varchar,char等數(shù)據(jù)類型的對象。 - getFloat():獲得數(shù)據(jù)庫里是Float類型的對象 - getDate():獲得數(shù)據(jù)庫里是Date類型的對象 - getBoolean():獲得數(shù)據(jù)庫里是Boolean類型的數(shù)據(jù) - 依序關(guān)閉使用的對象和連接 Result->Statement->Connection /** * 測試ResultSet的用法 * @author ibm * */ public class Demo04 { public static void main(String[] args) { Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { // 加載數(shù)據(jù)庫驅(qū)動 Class.forName("com.mysql.jdbc.Driver"); // 獲得connection對象 建立與數(shù)據(jù)庫連接 con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/testjdbc", "root", "123456"); String sql = "select * from t_user where id > ?"; ps = con.prepareStatement(sql); ps.setInt(1, 2); // 內(nèi)部就是個迭代器 rs = ps.executeQuery(); while (rs.next()) { System.out.println(rs.getInt(1) + "--" + rs.getString(2) + "--" + rs.getInt(3) + "--" + rs.getDate(4)); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (rs != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } if (ps != null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if (con != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } 批處理 - batch - 對于大量的批處理,建議使用Statement,因為PreparedStatement的預(yù)編譯空間有限,數(shù)據(jù)量特別大時,會發(fā)生異常。
package com.yf.jdbc.test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; /** * 測試批處理 * @author yangf * */ public class Demo05 { public static void main(String[] args) { Connection con = null; Statement stmt = null; ResultSet rs = null; try { // 加載數(shù)據(jù)庫驅(qū)動 Class.forName("com.mysql.jdbc.Driver"); // 獲得connection對象 建立與數(shù)據(jù)庫連接 con = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc", "root", "123456"); // jdbc中事物是自動提交的,我們設(shè)為手動提交 con.setAutoCommit(false); long start = System.currentTimeMillis(); stmt = con.createStatement(); for (int i = 0; i < 20000; i++) { stmt.addBatch("insert into t_user (username,pwd,regTime) values ('yangf "+ i + "', 6666 , now())"); } stmt.executeBatch(); con.commit(); long end = System.currentTimeMillis(); System.out.println("插入20000萬條數(shù)據(jù)耗時:" + (end - start) + "毫秒"); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (rs != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (con != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
|
|