1、什麼是jdbc
java database Connector java與數據庫的連接器
一套接口,是java代碼與數據庫的橋樑
2、重要接口和類
1)java.sql.Connection (連接接口--代表了java代碼與數據庫服務器之間的連接)
2)java.sql.Statement (語句接口--代表了語句對象,可以用來執行各種sql)
3)java.sql.ResultSet (結果集接口--代表查詢結果)
4)DriverManager (驅動管理器) 輔助類 -- 獲取Connection連接
5)java.sql.Driver (驅動接口)
6)java.sql.SQLException 檢查異常, 需要處理
###3
1) 加載驅動 (在新版的jdbc中可以省略此步驟)只需要執行一次即可
Class.forName("com.mysql.jdbc.Driver");// mysql 5.1
Class.forName("com.mysql.cj.jdbc.Driver"); // mysql 8.8
2) 創建連接,創建Connection對象
// jdbc:mysql: 稱爲連接協議
// localhost: mysql服務器的ip地址 連接本電腦用 localhost
// 3306: 連接端口號
// test3: 數據庫名稱
// serverTimezone=GMT%2B8 設置連接時區與數據庫服務器一致 (連接8.0 mysql時新增 )
String url = "jdbc:mysql://localhost:3306/test3?serverTimezone=GMT%2B8&useSSL=false"; // 數據庫的連接字符串
String username="root"; // 數據庫用戶名
String password="root"; // 數據庫的密碼(自己定義的數據庫密碼)
以上三個定義可以寫在工具類中方便以後的使用
Connection conn = DriverManager.getConnection(url, username, password);
常見問題:
(1):在連接過程中一旦發生異常:java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed
需要添加allowPublicKeyRetrieval=true
參數,此異常一種可能的發生情況是MySQL服務重啓後,立刻用jdbc連接時
(2):不寫 serverTimezone=GMT%2B8`參數,否則會出現異常:java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä',
另外`GMT%2B8`也必須加 ,否則會出現連接方和數據庫時區不一致問題
(3):WARN: Establishing SSL connection without server's identity verification is not recommended
要消除這個警告信息,需要加入參數`useSSL=false 參數之間連接用&
3) 創建Statement 對象
Statement stmt = conn.createStatement();
4) 執行sql語句(執行增刪改或查詢)
stmt.executeUpdate(sql) // 用來執行 insert, update, delete 返回結果是int 類型 表示影響的行數
stmt.executeQuery(sql) // 用來執行 select
stmt.execute(sql) //都可以執行
返回值是boolean類型 如果執行了增刪改,返回false, 如果執行的是查詢,那麼返回true,
5)結果集
ResultSet rs = stmt.executeQuery(sql);
rs.next();返回的是boolean值表示是否有下一條記錄
next()方法用來移動到下一行記錄 getXXX方法用來獲取某列數據
while (rs.next()) {
int sid = rs.getInt(1); //(1) 代表從第幾行開始
String sname = rs.getString(2);
Date birthday = rs.getDate(3);
String sex = rs.getString(4);
}
情況1: getXXX(int 列下標) 用來獲取結果集中某一列的數據,其中XXX爲數據類型,如果是字符串使用 getString 如果是整數,使用getInt ... ,列下標從1開始
情況2: getXXX(int 列名) 用來獲取結果集中某一列的數據,其中XXX爲數據類型,如果是字符串使用 getString 如果是整數,使用getInt
如:int deptno = rs.getInt("deptno");
String dname = rs.getString("dname");
String loc = rs.getString("loc");
6) 關閉資源 先打開的後關閉
rs.close(); // 關閉ResultSet
stmt.close(); // 關閉Statement對象
conn.close(); // 關閉數據庫連接
###4 獲取自增列的值 Statement.RETURN_GENERATED_KEYS 代表自增的值
Statement stmt = conn.createStatement();
String sql = "insert into student(sid,sname,birthday,sex) values (null,'XXX','1999-1-1','男')";
stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys();
rs.next();
System.out.println(rs.getInt(1));
###5 sql 注入×××問題
問題: Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
Statement stmt = conn.createStatement();
// 拼接字符串的辦法生成了sql語句
String sql = "select * from user where username='" +username+"' and password='"+password+"'";
如果結果爲:String password = "' or '1=1"; 會與之匹配從而登錄成功
解決方法: // PreparedStatement 預編譯的Statement ,可以避免SQL注入×××漏洞
// 讓代碼的可讀性更好
Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
// sql語句是預先準備好的, 用?作爲值的佔位符
String sql = "select * from USER where username=? and password=?";
PreparedStatement stmt = conn.prepareStatement(sql);
// 給sql語句中的? 賦值
stmt.setString(1, username); // 將username變量賦值給sql語句中第一個?, ?下標從1開始
stmt.setString(2, "aaa' or '1'='1"); // 會將整個值當做一個整體,把or當做了值而不是關鍵字
ResultSet rs = stmt.executeQuery();; // 會將sql語句以及通過set方法設置的參數值,一起發送給數據庫服務器
例: public static boolean login2(String deptno,String dname) {
Connection conn = null;
PreparedStatement pre = null;
ResultSet rst =null;
try {
conn = DriverManager.getConnection(URL, username, password);
String sql = "select * from emp where deptno=?and ename=?" ;
pre = conn.prepareStatement(sql);
pre.setString(1, deptno);
pre.setString(2, dname);
rst = pre.executeQuery();
if(rst.next()){
return true;
}else{
return false;
}
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("失敗",e); //無返回值拋出異常
}finally {
if(rst!=null){
try {
rst.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (pre!=null){
try {
pre.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}