1.JDBC 概念
概念:Java DataBase Connectivity Java數據庫連接,Java語言操作數據庫
本質:其實是官方(sun)定義的一套操作所有關系型數據庫的規則,既接口。各個數據庫廠商去實現這套這套接口,提供數據庫驅動jar包。
我們可以使用這套接口(JDBC)編程,真正執行的代碼是驅動jar包中的實現類。
2.快速入門
(1)導入驅動jar包 mysql-connector-java-5.1.37-bin.jar
1.復制mysql-connector-java-5.1.37-bin.jar到項目的libs目錄下
2.右鍵項目 add as library
(2)注冊驅動
(3)獲取數據庫連接對象 Connection
(4)定義sql
(5)獲取執行sql語句的對象 Statement
(6)執行sql,接收返回的結果
(7)處理結果
(8)釋放資源
public class JdbcDemo1 { public static void main(String[] args) throws Exception { //1.導入驅動jar包 //2.注冊驅動 Class.forName("com.mysql.jdbc.Driver"); //3.獲取數據庫連接對象 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "woaini1314"); //4.定義sql語句 String sql = "update emp set salary = 9999 where id = 1"; //5.獲取執行sql的對象 Statement Statement statement = conn.createStatement(); //6.執行sql int count = statement.executeUpdate(sql); //7.處理結果 System.out.println(count); //8.釋放資源 statement.close(); conn.close(); } }
3.JDBC各個類詳解
(1)DriverManager:驅動管理對象
*功能:
1.注冊驅動:告訴程序該使用哪一個數據庫驅動jar包
static void registerDriver(Driver driver):注冊與給定的驅動程序 DriverManager
寫代碼使用:Class.forName("com.mysql.jdbc.Driver"); - - > 來自導入的jar包
通過查看源碼發現:在com.mysql.jdbc.Driver類中存在靜態代碼塊
注意:mysql之后的驅動jar包可以省略注冊驅動的步驟
2.獲取數據庫連接
*方法:static connection DriverManager.getConnection(String url,String user,String password)
*參數:
*url:指定連接的路徑
*語法:jdbc:mysql:// IP地址(域名):端口號/數據庫名稱 如:jdbc:mysql://localhost:3306/db1
*細節:如果ip地址是本地並且端口號為3306 則可以省略不寫 jdbc:mysql:///db1
*user:用戶名
*password:密碼
(2)Connection:數據庫連接對象
*功能:
1.獲取執行sql的對象
*statement createStatament()
*Preparedstatement preparedStatament(String sql)
2.管理事務:
*開啟事務: setAutoCommit(boolean autoCommit) : 調用該方法設置參數為false,既開啟事務 手動提交
*提交事務:commit()
*回滾事務:rollback()
(3)Statement:執行Sql的對象
1.執行sql
1.boolean execute(String sql):可以執行任意的sql 了解
2.int executeUpdate(String sql):執行的是DML(insert、update、delete)語句、DDL(create、alter、drop)語句
*返回值:影響的行數,可以通過返回值的行數判斷DML語句是否執行成功 返回值 > 0 則執行成功 反之則失敗
3.ResultSet executeQuery(String sql):執行DQL(select)語句
(4)ResultSet:結果集對象,就是來封裝查詢結果的
*boolean next():游標向下移動一行,判斷當前行是否是最后一行末尾(是否有數據),如果是則返回false
*getXxx(參數):獲取數據
Xxx:代表數據類型 如:int getInt() String getString()
參數:int - - > 代表列的編號,從1開始 String - - > 代表列名稱
基本查詢:
注意:
正確使用步驟:
1.游標向下移動一行
2.判斷是否有數據
3.獲取數據

public class JdbcDemo2 { public static void main(String[] args) { //練習:往數據庫db3表中添加、修改、刪除 Statement stmt = null; //提升作用域 因為finally中要執行釋放資源 Connection conn = null; ResultSet rs = null; try { //1.注冊驅動 Class.forName("com.mysql.jdbc.Driver"); //2.定義sql String sql = "SELECT * from stu3"; //3.獲取connection對象 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "woaini1314"); //4.獲取執行sql的對象 statement stmt = conn.createStatement(); //5.執行sql rs = stmt.executeQuery(sql); //6.處理結果 //讓光標向下移動一行 //循環判斷 while (rs.next()){ String name = rs.getString("name"); int id = rs.getInt(1); System.out.println(id + "---" + name); }; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally { //7.釋放資源 //stmt.close(); //若用戶輸入密碼錯誤,要避免空指針異常 try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
(5)PrepareStatement:執行Sql的對象
練習:JDBC增刪改

public class JdbcDemo2 { public static void main(String[] args) { //練習:往數據庫db3表中添加、修改、刪除 Statement stmt = null; //提升作用域 因為finally中要執行釋放資源 Connection conn = null; try { //1.注冊驅動 Class.forName("com.mysql.jdbc.Driver"); //2.定義sql String sql = "insert into stu3 values(null,'joe')"; //3.獲取connection對象 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "woaini1314"); //4.獲取執行sql的對象 statement stmt = conn.createStatement(); //5.執行sql int count = stmt.executeUpdate(sql); //影響行數 //6.處理結果 System.out.println(count); if(count > 0){ System.out.println("添加成功"); }else { System.out.println("添加失敗"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally { //7.釋放資源 //stmt.close(); //若用戶輸入密碼錯誤,要避免空指針異常 if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }

public class JdbcDemo2 { public static void main(String[] args) { //練習:往數據庫db3表中添加、修改、刪除 Statement stmt = null; //提升作用域 因為finally中要執行釋放資源 Connection conn = null; try { //1.注冊驅動 Class.forName("com.mysql.jdbc.Driver"); //2.定義sql String sql = "UPDATE stu3 set name = 'Lindsey' where id = 2"; //3.獲取connection對象 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "woaini1314"); //4.獲取執行sql的對象 statement stmt = conn.createStatement(); //5.執行sql int count = stmt.executeUpdate(sql); //影響行數 //6.處理結果 System.out.println(count); if(count > 0){ System.out.println("修改成功"); }else { System.out.println("修改失敗"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally { //7.釋放資源 //stmt.close(); //若用戶輸入密碼錯誤,要避免空指針異常 if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
練習:定義一個方法,查詢emp表的數據,將其封裝為對象,然后裝載集合,返回

public class JdbcPractise { public static void main(String[] args) { List<Emp> list = new JdbcPractise().findAll(); for (Emp emp : list) { System.out.println(emp); } } /** * 查詢所有emp對象 * @return */ public List<Emp> findAll(){ //提升變量,以防報錯或空指針異常 ResultSet rs = null; Connection conn = null; Statement stmt = null; List<Emp> list = null; try { Class.forName("com.mysql.jdbc.Driver"); //獲取連接 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/pratise", "root", "woaini1314"); stmt = conn.createStatement(); //定義sql String sql = "select * from emp"; rs = stmt.executeQuery(sql); //遍歷結果集 封裝對象,封裝集合 Emp emp = null; //進行復用 防止反復進棧 list = new ArrayList<Emp>(); while (rs.next()){ int id = rs.getInt("id"); String ename = rs.getString("ename"); int job_id = rs.getInt("job_id"); int mgr = rs.getInt("mgr"); Date joindate = rs.getDate("joindate"); double salary = rs.getDouble("salary"); double bonus = rs.getDouble("bonus"); int dept_id = rs.getInt("dept_id"); //創建emp對象,並賦值 emp = new Emp(); emp.setId(id); emp.setEname(ename); emp.setJob_id(job_id); emp.setMgr(mgr); emp.setJoindate(joindate); emp.setSalary(salary); emp.setDept_id(dept_id); emp.setBonus(bonus); //裝載集合 list.add(emp); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally { if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return list; } }
4.JDBC工具類
目的:簡化書寫
*分析:
1.注冊驅動也抽取
2.抽取一個方法獲取連接對象
*需求:不想傳遞參數(麻煩),還得保證工具類的通用性
*解決方案:配置文件
jdbc.properties
url =
user =
password =
3.抽取一個方法釋放資源

import javax.swing.plaf.nimbus.State; import java.io.FileReader; import java.io.IOException; import java.net.URL; import java.sql.*; import java.util.Properties; /** * JDBC工具類 */ public class JDBCUtils { //只有靜態的變量才能被靜態方法和靜態代碼塊所訪問和使用 private static String url; private static String user; private static String password; private static String driver; /** * 文件的讀取,只需要讀取一次就可以拿到這些值。使用靜態代碼塊 */ static { //讀取資源文件,獲取值 try { //1.創建Properties 集合類 Properties pro = new Properties(); //獲取src文件下路徑的方式---> ClassLoader 類加載器 ClassLoader classLoader = JDBCUtils.class.getClassLoader(); URL resource = classLoader.getResource("jdbc.properties"); String path = resource.getPath(); System.out.println(path); //得到資源文件的絕對路徑 //2.加載文件 //pro.load(new FileReader("src/jdbc.properties")); pro.load(new FileReader(path)); //3.獲取屬性,並賦值 url = pro.getProperty("url"); user = pro.getProperty("user"); password=pro.getProperty("password"); driver = pro.getProperty("driver"); //注冊驅動 Class.forName(driver); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } /** * 獲取連接的方法 * @return 返回連接對象 */ public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url,user,password); } /** * 釋放資源 * @param stmt * @param conn */ public static void close(Statement stmt,Connection conn){ if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } //釋放資源重載方法 public static void close(ResultSet rs,Statement stmt, Connection conn){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }

import javax.swing.plaf.nimbus.State; import java.io.FileReader; import java.io.IOException; import java.net.URL; import java.sql.*; import java.util.Properties; /** * JDBC工具類 */ public class JDBCUtils { //只有靜態的變量才能被靜態方法和靜態代碼塊所訪問和使用 private static String url; private static String user; private static String password; private static String driver; /** * 文件的讀取,只需要讀取一次就可以拿到這些值。使用靜態代碼塊 */ static { //讀取資源文件,獲取值 try { //1.創建Properties 集合類 Properties pro = new Properties(); //獲取src文件下路徑的方式---> ClassLoader 類加載器 /* ClassLoader classLoader = JDBCUtils.class.getClassLoader(); URL resource = classLoader.getResource("jdbc.properties"); String path = resource.getPath(); System.out.println(path); //得到資源文件的絕對路徑*/ //2.加載文件 //pro.load(new FileReader("src/jdbc.properties")); pro.load(new FileReader("D:\\DB\\jdbc_basic\\src\\cn\\itcast\\jdbc\\jdbc.properties")); //3.獲取屬性,並賦值 url = pro.getProperty("url"); user = pro.getProperty("user"); password=pro.getProperty("password"); driver = pro.getProperty("driver"); //注冊驅動 Class.forName(driver); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } /** * 獲取連接的方法 * @return 返回連接對象 */ public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url,user,password); } /** * 釋放資源 * @param stmt * @param conn */ public static void close(Statement stmt,Connection conn){ if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } //釋放資源重載方法 public static void close(ResultSet rs,Statement stmt, Connection conn){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
練習:
需求:
1.通過鍵盤錄入用戶名和密碼
2.判斷用戶是否登錄成功
select * from user where username = " " and password = " ";
*如果這個sql有查詢結果,則登錄成功
步驟:
1.創建數據庫表user
CREATE TABLE USER( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(32), PASSWORD VARCHAR(32) ); SELECT * FROM USER; INSERT INTO USER VALUES(NULL,'zhangsan','123'); INSERT INTO USER VALUES(NULL,'lisi','456');

import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; public class JdbcLogin { public static void main(String[] args) { //1.鍵盤錄入,接收用戶名和密碼 Scanner sc = new Scanner(System.in); System.out.println("請輸入用戶名"); String username = sc.nextLine(); System.out.println("請輸入密碼"); String password = sc.nextLine(); //2.調用方法 boolean flag = new JdbcLogin().login(username, password); //3.判斷結果 if(flag){ //登錄成功 System.out.println("登錄成功"); }else { System.out.println("賬號或密碼錯誤"); } } /** * 登錄方法 */ public boolean login(String username, String password){ if(username==null && password==null){ return false; } //連接數據庫判斷是否登錄成功 Connection conn = null; Statement stmt = null; ResultSet rs = null; //獲取數據庫連接 try { conn = JDBCUtils.getConnection(); //2.定義sql String sql = "select * from user where username = '"+username+"' and password = '"+password+"'"; //3.獲取執行sql的對象 stmt = conn.createStatement(); //4.執行查詢 rs = stmt.executeQuery(sql); //5.判斷 return rs.next(); } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtils.close(rs,stmt,conn); } return false; //如果執行到這,說明出現了異常,返回false就好了 } }
5.PreparedStatement解決sql注入問題
1.Sql注入問題 : 在拼接sql時,有一些sql的特殊關鍵字參與字符串的拼接。會造成安全性問題
1.隨便輸入用戶名,輸入密碼:a' or 'a' = 'a
2.sql:select * from user where username = 'asgasg' and password = a' or 'a' = 'a
2.解決sql注入問題:使用PrepareStatement對象來解決
3.預編譯SQL:參數使用 ? 作為占位符
4.步驟:
(1)導入驅動jar包 mysql-connector-java-5.1.37-bin.jar
(2)注冊驅動
(3)獲取數據庫連接對象 Connection
(4)定義sql
*注意:sql的參數使用 ? 作為占位符 如:select * from user where username = ? and password = ?
(5)獲取執行sql語句的對象 PreparedStatement Connection.PreparedStatement(String sql)
(6)給?賦值
*方法:setXxx(參數1,參數2) 參數1 是 ? 的位置編號,從1開始,參數2是問號的值
(7)執行sql,接收返回的結果,不需要傳遞sql語句
(8)處理結果
(9)釋放資源
5.注意:后期都會只有PreparedStatemet來完成增刪改查的所有操作 因為可以防止sql注入 而且效率更高

/** * 登錄方法 */ public boolean login(String username, String password){ if(username==null && password==null){ return false; } //連接數據庫判斷是否登錄成功 Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; //獲取數據庫連接 try { conn = JDBCUtils.getConnection(); //2.定義sql String sql = "select * from user where username = ? and password = ?"; //3.獲取執行sql的對象 pstmt = conn.prepareStatement(sql); //給?賦值 pstmt.setString(1,username); pstmt.setString(2,password); //4.執行查詢 rs = pstmt.executeQuery(); //5.判斷 return rs.next(); } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtils.close(rs,pstmt,conn); } return false; //如果執行到這,說明出現了異常,返回false就好了 }
JDBC管理事務
管理事務:
*開啟事務: setAutoCommit(boolean autoCommit) : 調用該方法設置參數為false,既開啟事務 手動提交
*在執行sql之前開啟事務
*提交事務:commit()
*當所有sql都執行完提交事務
*回滾事務:rollback()
*在catch異常中回滾事務

public class JdbcOperateAffair { /** * JDBC管理事務 */ public static void main(String[] args) { Connection conn = null; PreparedStatement pstmt = null; PreparedStatement pstmt2 = null; try { conn = JDBCUtils.getConnection(); //開啟事務 conn.setAutoCommit(false); //2.定義sql //張三減500 李四+500 String sql = "update account set balance = balance - ? where id = ?"; String sql2 = "update account set balance = balance + ? where id = ?"; //3.獲取執行sql的對象 pstmt = conn.prepareStatement(sql); pstmt2 = conn.prepareStatement(sql2); //4.設置參數 pstmt.setDouble(1,500); pstmt.setInt(2,1); pstmt2.setDouble(1,500); pstmt2.setInt(2,2); //5.執行sql pstmt.executeUpdate(); pstmt2.executeUpdate(); //提交事務 conn.commit(); } catch (Exception e) { //出異常了則進行事務的異常 try { if(conn!=null){ conn.rollback();} } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { JDBCUtils.close(pstmt,conn); JDBCUtils.close(pstmt2,null); } } }