Day5 JDBC
JDBC的簡介
Java? Database?Connectivity:連接數(shù)據(jù)庫技術(shù)。
SUN公司為了簡化、統(tǒng)一對數(shù)據(jù)庫的操作,定義了一套Java操作數(shù)據(jù)庫的規(guī)范(接口),使用同一套程序操作不同的數(shù)據(jù)庫,稱之為JDBC。
簡單的說,JDBC的意義在于在Java程序中執(zhí)行SQL語句。
JDBC開發(fā)支持jar:
java.sql
javax.sql
驅(qū)動包
JDBC的工作原理
?JDBC中核心類:DriverManager驅(qū)動管理器
JDBC主要分為兩層,第一層為Java的接口層,主要面向Java的應(yīng)用程序開發(fā)者,它定義了操作數(shù)據(jù)庫的各種功能的接口,第二層為數(shù)據(jù)庫驅(qū)動層,為數(shù)據(jù)庫供應(yīng)商提供了注冊其數(shù)據(jù)庫產(chǎn)品驅(qū)動程序的接口,兩者之間是通過驅(qū)動管理器來負(fù)責(zé)協(xié)調(diào)和管理的。由于JDBC為所有支持的數(shù)據(jù)庫提供了統(tǒng)一的API接口,因此在實(shí)際的開發(fā)中,如果軟件產(chǎn)品被要求同時支持多種數(shù)據(jù)庫平臺,其間主要的差異將來自于不同數(shù)據(jù)庫產(chǎn)品在特殊SQL語句方面的差異,至于調(diào)用接口方面,如果沒有使用極為依賴數(shù)據(jù)庫平臺的接口API,那么該部分程序代碼將不用作出任何改變。以下我們將通過示例代碼的方式逐步了解JDBC中提供的API接口。
JDBC的開發(fā)步驟
?1.實(shí)現(xiàn)驅(qū)動注冊(DriverManager)
?2.建立連接
?3.創(chuàng)建以及發(fā)送SQL指令
?4.獲取以及處理響應(yīng)
?5.釋放資源
JDBC的入門案例
?1.導(dǎo)入驅(qū)動包,建立一個lib文件夾存放程序需要的一些jar包,建立之后將jar包復(fù)制黏貼進(jìn)到lib下
?
?
?2.簡單案例
程序代碼
package test;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 JDBCTest {public static void main(String[] args) throws Exception {// 1.借助DriverManager實(shí)現(xiàn)驅(qū)動的注冊(mysql驅(qū)動就在DriverManager中管理)//DriverManager.registerDriver(new Driver());// 反射(DriverManager.registerDriver()注冊的唯一方法),注冊驅(qū)動Class.forName("com.mysql.jdbc.Driver");// 2.建立連接// jdbc:mysql://localhost:3306/db1711// 協(xié)議:子協(xié)議://IP:端口/數(shù)據(jù)庫Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1711",//url統(tǒng)一資源定位符(路徑)和mysql DBMS的哪個數(shù)據(jù)庫建立連接"root",//user用戶"123456");//password密碼// 查看是否連接成功// System.out.println(conn);//com.mysql.jdbc.JDBC4Connection@4d405ef7// 3.發(fā)送sql指令String sql = "select * from emp";// 創(chuàng)建Statement的實(shí)現(xiàn)類的對象Statement stmt = conn.createStatement();// executeUpdate():增刪該,返回的是int類型,影響的行數(shù),0是失敗// executeQuery():查詢,返回的是結(jié)果集ResultSet rs = stmt.executeQuery(sql);// 4.結(jié)果集的處理()// rs.next():boolean類型,游標(biāo),沒有值的話返回falsewhile(rs.next()) {//遍歷每一行的數(shù)據(jù)// 依次獲取每一列的數(shù)據(jù)int empno = rs.getInt("empno");String ename = rs.getString("ename");System.out.println(empno+"\t"+ename);}// 5.釋放資源 rs.close();stmt.close();conn.close();}}?顯示結(jié)果
7369 SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7788 SCOTT 7839 KING 7844 TURNER 7876 ADAMS 7900 JAMES 7902 FORD 7934 MILLER?
核心API詳解
DriverManager
驅(qū)動注冊
第一種方式,會造成DriverManager中產(chǎn)生兩個一樣的驅(qū)動,并會對具體的驅(qū)動類產(chǎn)生依賴。
// 1.借助DriverManager實(shí)現(xiàn)驅(qū)動的注冊(mysql驅(qū)動就在DriverManager中管理) DriverManager.registerDriver(new Driver());?
第二種方式,反射加載(推薦),注冊一次,在driver類加載的時候就注冊了
// 反射(DriverManager.registerDriver()注冊的唯一方法),注冊驅(qū)動Class.forName("com.mysql.jdbc.Driver");?
Driver部分原碼
public class Driver extends NonRegisteringDriver implements java.sql.Driver {// ~ Static fields/initializers// ---------------------------------------------//// Register ourselves with the DriverManager// static {try {java.sql.DriverManager.registerDriver(new Driver());} catch (SQLException E) {throw new RuntimeException("Can't register driver!");}}}
?
增刪改查案例
增
1 public static void insert(int deptno,String dname,String loc) throws Exception{ 2 Class.forName("com.mysql.jdbc.Driver"); 3 Connection conn = DriverManager.getConnection( 4 "jdbc:mysql://localhost:3306/db1711", 5 "root", 6 "123456"); 7 Statement stmt = conn.createStatement(); 8 String sql = "INSERT INTO dept VALUES("+deptno+",'"+dname+"','"+loc+"')"; 9 int num = stmt.executeUpdate(sql); 10 System.out.println(num); 11 stmt.close(); 12 conn.close(); 13 14 } View Code刪
1 public static void delete(int deptno) throws Exception{ 2 Class.forName("com.mysql.jdbc.Driver"); 3 Connection conn = DriverManager.getConnection( 4 "jdbc:mysql://localhost:3306/db1711", 5 "root", 6 "123456"); 7 Statement stmt = conn.createStatement(); 8 String sql = "delete from dept where deptno = "+deptno+""; 9 int nums = stmt.executeUpdate(sql); 10 System.out.println(nums); 11 stmt.close(); 12 conn.close(); 13 } View Code改
1 public static void update(int deptno,String loc) throws Exception{ 2 Class.forName("com.mysql.jdbc.Driver"); 3 Connection conn = DriverManager.getConnection( 4 "jdbc:mysql://localhost:3306/db1711", 5 "root", 6 "123456"); 7 Statement stmt = conn.createStatement(); 8 String sql = "update dept set deptno = "+deptno+" where loc = '"+loc+"'"; 9 int nums = stmt.executeUpdate(sql); 10 System.out.println(nums); 11 stmt.close(); 12 conn.close(); 13 } View Code查
1 public static void query() throws Exception{ 2 // 1.借助DriverManager實(shí)現(xiàn)驅(qū)動的注冊(mysql驅(qū)動就在DriverManager中管理) 3 //DriverManager.registerDriver(new Driver()); 4 // 反射(DriverManager.registerDriver()注冊的唯一方法),注冊驅(qū)動 5 Class.forName("com.mysql.jdbc.Driver"); 6 7 // 2.建立連接 8 // jdbc:mysql://localhost:3306/db1711 9 // 協(xié)議:子協(xié)議://IP:端口/數(shù)據(jù)庫 10 Connection conn = DriverManager.getConnection( 11 "jdbc:mysql://localhost:3306/db1711",//url統(tǒng)一資源定位符(路徑)和mysql DBMS的哪個數(shù)據(jù)庫建立連接 12 "root",//user用戶 13 "123456");//password密碼 14 // 查看是否連接成功 15 // System.out.println(conn);//com.mysql.jdbc.JDBC4Connection@4d405ef7 16 17 // 3.發(fā)送sql指令 18 String sql = "select * from emp"; 19 // 創(chuàng)建Statement的實(shí)現(xiàn)類的對象 20 Statement stmt = conn.createStatement(); 21 // executeUpdate():增刪該,返回的是int類型,影響的行數(shù),0是失敗 22 // executeQuery():查詢,返回的是結(jié)果集 23 ResultSet rs = stmt.executeQuery(sql); 24 25 // 4.結(jié)果集的處理() 26 // rs.next():boolean類型,游標(biāo),沒有值的話返回false 27 while(rs.next()) {//遍歷每一行的數(shù)據(jù) 28 // 依次獲取每一列的數(shù)據(jù) 29 int empno = rs.getInt("empno"); 30 String ename = rs.getString("ename"); 31 System.out.println(empno+"\t"+ename); 32 } 33 34 // 5.釋放資源 35 rs.close(); 36 stmt.close(); 37 conn.close(); 38 } View Code登錄的問題
SQL注入
1 // 1.注冊驅(qū)動 2 Class.forName("com.mysql.jdbc.Driver"); 3 // 2.建立連接 4 Connection conn = DriverManager.getConnection( 5 "jdbc:mysql://localhost:3306/bd1711", 6 "root", 7 "root"); 8 //3.發(fā)送sql, ?占位符 9 String sql = "select * from user where uname = ? and password = ? "; 10 //支持sql的預(yù)編譯(語法檢查,語義檢查 ... 查詢) 11 PreparedStatement ps = conn.prepareStatement(sql); 12 //賦值 13 ps.setString(1, name); 14 ps.setString(2, pwd); 15 //發(fā)送命令 16 ResultSet rs = ps.executeQuery(); 17 //4.處理響應(yīng)結(jié)果 18 if(rs.next()){ 19 System.out.println("登陸成功"); 20 }else{ 21 System.out.println("登錄失敗"); 22 } 23 //5.釋放資源 24 rs.close(); 25 ps.close(); 26 conn.close(); 27 28 1. preparestatement能夠避免sql的注入攻擊,安全性更高。 29 2. preparedStatment實(shí)現(xiàn)預(yù)編譯,因此在批量的數(shù)據(jù)操作中減少語法檢查的時間,效率高。 30 3. 在批處理中,preparedstatement只能批量處理單一類型的操作;statement可以一次處理增刪改等多種類型的操作。 31 32 //使用preparedStatement實(shí)現(xiàn)批處理 33 // 1.注冊驅(qū)動 34 Class.forName("com.mysql.jdbc.Driver"); 35 // 2.建立連接 36 Connection conn = DriverManager.getConnection( 37 "jdbc:mysql://localhost:3306/bd1711", 38 "root", 39 "root"); 40 //3.發(fā)送sql 41 String sql = "delete from user where uid = ?"; 42 //預(yù)編譯 43 PreparedStatement ps = conn.prepareStatement(sql); 44 //賦值 45 ps.setInt(1, 1); 46 ps.addBatch(); 47 48 ps.setInt(1, 2); 49 ps.addBatch(); 50 51 //4.執(zhí)行和處理響應(yīng) 52 int[] rows = ps.executeBatch(); 53 System.out.println(Arrays.toString(rows)); 54 55 //5.釋放資源 56 ps.close(); 57 conn.close(); 58 59 //使用Statement實(shí)現(xiàn)批處理 60 String sql2 = "insert"; 61 String sql3 = "delete"; 62 Statement stmt = conn.createStatement(); 63 stmt.addBatch(sql2); 64 stmt.addBatch(sql3); 65 stmt.executeBatch(); View Code開發(fā)DAO
data access object
分層開發(fā)(實(shí)現(xiàn)代碼復(fù)用)
DAO主要負(fù)責(zé)與數(shù)據(jù)庫之間的交互。
問題:
1.硬編碼:配置文件
如何使用外部配置文件:
? properties配置文件:
?
//創(chuàng)建properties對象Properties properties =new Properties();//將propertes文件加載為流InputStream is = EmpDao2.class.getClassLoader().getResourceAsStream("jdbc.properties");//加載 properties.load(is);//通過key值獲取value值String driver = properties.getProperty("driver");String url = properties.getProperty("url");String user = properties.getProperty("user");String pwd = properties.getProperty("pwd");// 1.注冊驅(qū)動 Class.forName(driver);conn = DriverManager.getConnection(url,user,pwd);封裝BASEDAO
封裝basedao
1 package dao; 2 3 import java.lang.reflect.Field; 4 import java.sql.Connection; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.ResultSetMetaData; 8 import java.sql.SQLException; 9 import java.util.ArrayList; 10 import java.util.List; 11 12 import util.JdbcUtils; 13 14 /** 15 * 16 * @author Administrator 17 * 所有的dao的父類(通用的增刪改查) 18 */ 19 public class BaseDao { 20 21 protected Connection conn = null; 22 protected PreparedStatement ps = null; 23 protected ResultSet rs = null; 24 25 //通用的增刪改emp dept user 26 //1.insert update delete / emp dept user : sql ? ? 27 //2.賦值的參數(shù)的個數(shù)和類型不能確定 Object[] 28 public int executeUpdate(String sql,Object[] params){ 29 int rows = 0; 30 try { 31 //2.獲取連接 32 conn = JdbcUtils.getConnecton(); 33 //3.發(fā)送sql指令 34 //預(yù)編譯 35 ps = conn.prepareStatement(sql); 36 //賦值 37 for(int i=0;i<params.length;i++){ 38 ps.setObject(i+1, params[i]); 39 } 40 //處理 41 rows = ps.executeUpdate(); 42 } catch (SQLException e) { 43 e.printStackTrace(); 44 } catch (Exception e) { 45 e.printStackTrace(); 46 }finally{ 47 JdbcUtils.closeRes(rs, ps, conn); 48 } 49 return rows; 50 } 51 52 //通用查詢 53 public<T> List<T> executeQuery(String sql,Object[] params,Class<T> clz){ 54 //定義集合 55 List<T> lists = new ArrayList<>(); 56 try { 57 //1.獲取連接 58 conn=JdbcUtils.getConnecton(); 59 //2.發(fā)送sql 60 ps = conn.prepareStatement(sql); 61 for(int i=0;i<params.length;i++){ 62 ps.setObject(i+1, params[i]); 63 } 64 ResultSet rs = ps.executeQuery(); 65 //元數(shù)據(jù):解釋數(shù)據(jù)的數(shù)據(jù) 66 ResultSetMetaData md = rs.getMetaData(); 67 //查詢的字段的總數(shù) 68 int count = md.getColumnCount(); 69 //3.處理 70 while(rs.next()){//遍歷一行就需要創(chuàng)建一個對象進(jìn)行封裝 71 //創(chuàng)建t對象 (調(diào)用t的class對象創(chuàng)建t對象,調(diào)用無參構(gòu)造創(chuàng)建對象) 72 T t = clz.newInstance(); 73 //獲取每個字段的值(遍歷獲取每行中每個字段的值) 74 for(int i=0;i<count;i++){ 75 //先獲取字段名稱 76 String name = md.getColumnName(i+1); 77 //根據(jù)字段名稱獲取字段的值 78 Object value = rs.getObject(name); 79 //根據(jù)字段名稱獲取相應(yīng)的屬性,將字段的值賦給屬性 80 Field field = clz.getDeclaredField(name); 81 //設(shè)置允許賦值 82 field.setAccessible(true); 83 //賦值 84 if(value!=null){ 85 field.set(t, value); 86 } 87 } 88 //添加到list集合 89 lists.add(t); 90 } 91 } catch (SQLException e) { 92 // TODO Auto-generated catch block 93 e.printStackTrace(); 94 } catch (Exception e) { 95 // TODO Auto-generated catch block 96 e.printStackTrace(); 97 }finally{ 98 JdbcUtils.closeRes(rs, ps, conn); 99 } 100 return lists; 101 } 102 103 104 105 106 } View Code調(diào)用basedao
1 package dao; 2 import java.sql.Connection; 3 import java.sql.Date; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import java.util.ArrayList; 7 import java.util.List; 8 import entity.Emp; 9 import util.JdbcUtils; 10 11 public class EmpDao3 extends BaseDao{ 12 13 //查詢所有 14 public List<Emp> queryAll(){ 15 String sql = "select * from emp"; 16 Object[] params = {}; 17 return executeQuery(sql, params, Emp.class); 18 } 19 20 //增加 21 public int insert(Emp emp){ 22 String sql = "insert into emp(empno,ename,deptno) values(?,?,?)"; 23 Object[] params = { emp.getEmpno(),emp.getEname(),emp.getDeptno() }; 24 return executeUpdate(sql, params); 25 } 26 27 public int delete(int empno){ 28 String sql = "delete from emp where empno=? "; 29 Object[] params = { empno }; 30 return executeUpdate(sql, params); 31 } 32 33 public static void main(String[] args) { 34 EmpDao3 dao = new EmpDao3(); 35 System.out.println(dao.queryAll()); 36 } 37 } View Code?
總結(jié)
- 上一篇: 关闭socket以及Socket选项
- 下一篇: 简单的java多线程源码分享(二)