Java工程師培訓課(十六【新的領域】)
夜光序言:
人生最糟的不是失去愛的人,而是因為太愛一個人,而失去了自己。
正文:
JDBC入門
1.1 回顧
之前操作mysql資料庫:
1)使用mysql客戶端工具
2)使用客戶端連線mysql伺服器
3)傳送sql語句到mysql伺服器,執行
1.2 什麼是JDBC?
使用java程式傳送sql語句到資料庫伺服器端執行,這叫用到了JDBC技術!!!!
jdbc是Oracle-Sun公司設計的一套專門用於java程式操作資料庫的介面。
1.3 使用jdbc傳送sql條件
連線mysql資料庫:
資料庫主機
埠
資料庫使用者名稱
資料庫密碼
連線的資料庫
1.4 JDBC的核心API
|-Driver介面: 資料庫驅動程式的介面,所有具體資料庫廠商需要的驅動程式需要實現次介面。
Connection connect(String url, Properties info) 用於獲取資料庫連線
|-Connection介面:與具體的資料庫的連線物件。
Statement createStatement() 建立一個靜態sql語句物件
PreparedStatement prepareStatement(String sql) 建立預編譯的sql語句物件
CallableStatement prepareCall(String sql) 建立儲存過程的sql語句物件
|-Statement介面:用於執行靜態 SQL 語句
int executeUpdate(String sql) 執行更新操作的sql語句 (create/alter/drop/insert/update/delete)
ResultSet executeQuery(String sql) 執行查詢操作的sql語句
(select)
|- PreparedStatement
int executeUpdate() 執行更新操作的sql語句
ResultSet executeQuery() 執行查詢操作的sql語句
|- CallableStatement介面:用於執行 SQL 儲存過程的介面(是PreparedStatement的子 介面)
ResultSet executeQuery() 執行儲存過程的sql語句
|- ResultSet介面:結果集物件。 儲存所有資料庫查詢的結果,用該物件進行資料遍歷。
boolean next() : 把游標移動到下一行。如果下一行有資料,返回true,如果沒有下一行數 據,返回false。
getXXX(列索引|列欄位名稱): 獲取欄位的資料
2 Statement物件執行SQL操作
2.1 執行DDL操作
/** * 通過jdbc執行DDL語句 * @author APPle * */ public class Demo1 { //資料庫的連線的URL private static String url = "jdbc:mysql://localhost:3306/day17"; //資料庫使用者名稱 private static String user = "root"; //資料庫密碼 private static String password = "root";
public static void main(String[] args){ Connection conn = null; Statement stmt = null; try { //1.驅動驅動程式 Class.forName("com.mysql.jdbc.Driver"); //2.從驅動程式管理類獲取連線 conn = DriverManager.getConnection(url, user, password); //3.通過Connection物件獲取Statement物件 stmt = conn.createStatement(); //4.準備sql語句 String sql = "CREATE TABLE student(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20),gender VARCHAR(2))"; //5.執行sql語句,返回結果 int count = stmt.executeUpdate(sql);
System.out.println("影響了"+count+"行"); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } finally{ //6.關閉資源(先關閉statement,再關閉connection) if(stmt!=null) try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } if(conn!=null) try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } } |
2.2 執行DML操作
/** * 通過jdbc執行DML語句(insert/update/delete) * @author APPle * */ public class Demo2 { //資料庫的連線的URL private static String url = "jdbc:mysql://localhost:3306/day17"; //資料庫使用者名稱 private static String user = "root"; //資料庫密碼 private static String password = "root"; /** * 執行插入操作 */ @Test public void test1(){ Connection conn = null; Statement stmt = null; try { //註冊驅動 Class.forName("com.mysql.jdbc.Driver"); //獲取連線 conn = DriverManager.getConnection(url, user, password); //建立Statment物件 stmt = conn.createStatement(); //準備sql String sql = "INSERT INTO student(NAME,gender) VALUES('張三','男')"; //執行sql,返回結果 int count = stmt.executeUpdate(sql); System.out.println("影響了"+count+"行"); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } finally{ //關閉資源 if(stmt!=null) try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } if(conn!=null) try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } }
/** * 執行更新操作 */ @Test public void test2(){ Connection conn = null; Statement stmt = null; //宣告外部變數 String name = "陳六"; int id=2; try { //註冊驅動 Class.forName("com.mysql.jdbc.Driver"); //獲取連線 conn = DriverManager.getConnection(url, user, password); //建立Statment物件 stmt = conn.createStatement(); //準備sql String sql = "UPDATE student SET NAME='"+name+"' WHERE id="+id+""; //變數和String拼接sql //執行sql,返回結果 int count = stmt.executeUpdate(sql); System.out.println("影響了"+count+"行"); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } finally{ //關閉資源 if(stmt!=null) try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } if(conn!=null) try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } }
/** * 執行刪除操作 */ @Test public void test3(){ Connection conn = null; Statement stmt = null; //宣告外部變數 int id=2; try { //註冊驅動 Class.forName("com.mysql.jdbc.Driver"); //獲取連線 conn = DriverManager.getConnection(url, user, password); //建立Statment物件 stmt = conn.createStatement(); //準備sql String sql = "DELETE FROM student WHERE id="+id+""; //變數和String拼接sql //執行sql,返回結果 int count = stmt.executeUpdate(sql); System.out.println("影響了"+count+"行"); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } finally{ //關閉資源 if(stmt!=null) try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } if(conn!=null) try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } } |
2.3 執行DQL查詢操作
/** * 使用jdbc執行DQL語句(select) * @author APPle * */ public class Demo3 { //資料庫的連線的URL private static String url = "jdbc:mysql://localhost:3306/day17"; //資料庫使用者名稱 private static String user = "root"; //資料庫密碼 private static String password = "root";
public static void main(String[] args) { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { //註冊驅動 Class.forName("com.mysql.jdbc.Driver"); //獲取連線 conn = DriverManager.getConnection(url, user, password); //建立Statement物件 stmt = conn.createStatement(); //準備sql String sql = "SELECT * FROM student";
rs = stmt.executeQuery(sql);
//移動游標到下一行 //rs.next(); /** * 注意: * 1)如果游標在第一行之前,使用rs.getXX()獲取列值,報錯:Before start of result set * 2)如果游標在最後一行之後,使用rs.getXX()獲取列值,報錯:After end of result set */
//獲取列值 /*if(rs.next()){ //使用列索引
int id = rs.getInt(1); String name = rs.getString(2); String gender = rs.getString(3);
//使用列名稱 int id = rs.getInt("id"); String name = rs.getString("name"); String gender = rs.getString("gender"); System.out.println(id+"\t"+name+"\t"+gender+"\t"); }*/
//迭代結果集 while(rs.next()){ //使用列索引 /* int id = rs.getInt(1); String name = rs.getString(2); String gender = rs.getString(3); */ //使用列名稱 int id = rs.getInt("id"); String name = rs.getString("name"); String gender = rs.getString("gender"); System.out.println(id+"\t"+name+"\t"+gender+"\t"); }
} catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } finally{ if(rs!=null) try { rs.close(); } catch (SQLException e1) { e1.printStackTrace(); throw new RuntimeException(e1); } //關閉資源 if(stmt!=null) try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } if(conn!=null) try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } }
} } |
3 PreparedStatement物件執行SQL操作
/** * 使用PreparedStatement執行sql語句 * @author APPle * */ public class Demo1 {
/** * 插入操作 */ @Test public void test1(){ Connection conn = null; PreparedStatement stmt = null; try{ //獲取連線 conn = JdbcUtil.getConnection(); String sql = "INSERT INTO student(NAME,gender) VALUES(?,?)"; //預編譯sql:使用?號代替引數值。一個?號代表一個引數值 //建立PreparedStatement物件,執行預編譯的sql語句 stmt = conn.prepareStatement(sql); //設定引數 /** * 引數一: 引數位置。從1開始 * 引數二: 引數實際值 * 注意: 所有引數必須要賦值 */ stmt.setString(1, "rose"); stmt.setString(2, "女"); //傳送引數,執行sql語句 int count = stmt.executeUpdate(); System.out.println(count); }catch(Exception e){ e.printStackTrace(); throw new RuntimeException(e); }finally{ //關閉資源 JdbcUtil.close(conn, stmt, null); } }
/** * 修改操作 */ @Test public void test2(){ Connection conn = null; PreparedStatement stmt = null; //宣告變數 String name = "jacky"; int id = 8; try{ //獲取連線 conn = JdbcUtil.getConnection(); String sql = "UPDATE student SET NAME=? WHERE id=?"; //預編譯sql:使用?號代替引數值。一個?號代表一個引數值 //建立PreparedStatement物件,執行預編譯的sql語句 stmt = conn.prepareStatement(sql); //設定引數 stmt.setString(1,name); stmt.setInt(2, id); //傳送引數,執行sql語句 int count = stmt.executeUpdate(); System.out.println(count); }catch(Exception e){ e.printStackTrace(); throw new RuntimeException(e); }finally{ //關閉資源 JdbcUtil.close(conn, stmt, null); } }
/** * 刪除操作 */ @Test public void test3(){ Connection conn = null; PreparedStatement stmt = null; //宣告變數 int id = 8; try{ //獲取連線 conn = JdbcUtil.getConnection(); String sql = "DELETE FROM student WHERE id=?"; //預編譯sql:使用?號代替引數值。一個?號代表一個引數值 //建立PreparedStatement物件,執行預編譯的sql語句 stmt = conn.prepareStatement(sql); //設定引數 //任何型別都可以使用setObject進行賦值 stmt.setObject(1, id); //傳送引數,執行sql語句 int count = stmt.executeUpdate(); System.out.println(count); }catch(Exception e){ e.printStackTrace(); throw new RuntimeException(e); }finally{ //關閉資源 JdbcUtil.close(conn, stmt, null); } }
/** * 查詢操作 */ @Test public void test4(){ Connection conn = null; PreparedStatement stmt = null; //宣告變數 String name = "張%"; try{ //獲取連線 conn = JdbcUtil.getConnection(); String sql = "SELECT * FROM student WHERE NAME LIKE ?"; //建立PreparedStatement,預編譯sql語句 stmt = conn.prepareStatement(sql); //設定引數 stmt.setObject(1, name); //傳送引數,執行sql,返回結果集 ResultSet rs = stmt.executeQuery(); //遍歷結果集 while(rs.next()){ int id = rs.getInt("id"); String nameStr = rs.getString("name"); String gender = rs.getString("gender"); System.out.println(id+"\t"+nameStr+"\t"+gender+"\t"); } }catch(Exception e){ e.printStackTrace(); throw new RuntimeException(e); }finally{ //關閉資源 JdbcUtil.close(conn, stmt, null); } }
} |
==============Statement和PreparedStatement的區別==========================================
一、語法結構不同
1)Statment執行靜態sql語句,且sql可以拼接。
2)PreparedStatement可以先執行預編譯的sql語句,在預編譯sql語句中使用?進行引數佔位,後面 在進行引數賦值
二、原理不同
1)Statement不能進行sql快取
2)而PreparedStatement可以進行sql快取,執行效率會比Statement快!!!
三、安全性不同
1)Statement存在sql注入的風險
2)而PreparedStatement可以有效防止使用者注入。
4 CallableStatement物件執行儲存過程
4.1 執行帶輸入引數的儲存過程
/** * 執行帶有輸入引數儲存過程 */ @Test public void test1(){ Connection conn = null; CallableStatement stmt = null; ResultSet rs = null; try{ //獲取連線 conn = JdbcUtil.getConnection(); //建立CallableStatement物件 String sql = "CALL pro_findById(?)";//預編譯sql、可以帶?號 //執行預編譯的sql stmt = conn.prepareCall(sql); //設定引數 stmt.setInt(1, 4); //傳送引數,執行sql,返回結果 rs = stmt.executeQuery();// 注意: 執行儲存過程必須使用exeuteQuery!!!! //遍歷結果 while(rs.next()){ int id = rs.getInt("id"); String name = rs.getString("name"); String gender = rs.getString("gender"); System.out.println(id+"\t"+name+"\t"+gender+"\t"); } }catch(Exception e){ e.printStackTrace(); throw new RuntimeException(e); }finally{ //關閉資源 JdbcUtil.close(conn, stmt, rs); } } |
4.2 執行帶有輸出引數的儲存過程
/** * 執行帶有輸出引數儲存過程 */ @Test public void test2(){ Connection conn = null; CallableStatement stmt = null; try{ //獲取連線 conn = JdbcUtil.getConnection(); String sql = "CALL pro_findById2(?,?)"; // 第一個引數時輸入引數,第二個引數是輸出引數 //建立CallableStatement物件 stmt = conn.prepareCall(sql); //設定輸入引數 stmt.setObject(1, 4); //註冊一個輸出引數 /** * 引數一: 引數位置 * 引數二: 表示儲存過程中的OUT引數的資料庫型別 */ stmt.registerOutParameter(2, java.sql.Types.VARCHAR);
//傳送引數,執行儲存過程 stmt.executeQuery();
/** * 如何獲取儲存過程的返回值:OUT引數值。使用getXXX方法 */ String name = stmt.getString(2);//和預編譯語句中的引數位置保持一致!!!! System.out.println("結果:"+name); }catch(Exception e){ e.printStackTrace(); throw new RuntimeException(e); }finally{ //關閉資源 JdbcUtil.close(conn, stmt, null); } } |
5 使用類路徑載入資原始檔
/** * 使用類路徑的方式載入db.properties檔案 */ //1.得到位元組碼物件 Class clazz = JdbcUtil.class; //2.通過方法載入檔案,使用類路徑方式 // / : 表示類路徑的根目錄(放class位元組碼檔案目錄) // java專案: bin目錄下 // web專案: WEB-INF/classes目錄下 InputStream in = clazz.getResourceAsStream("/db.properties"); // 從類路徑的根目錄下開始找 //InputStream in = clazz.getResourceAsStream("db.properties"); // 檔案和當前類處於同一個目錄 prop.load(in); |
Class.getResourceAsStream("/db.properties");
Class.getResourceAsStream("db.properties");
這裡的 斜槓 / 表示當前專案的類路徑的根目錄。
當前專案是java專案,/ 在專案的bin目錄下
當前專案是web專案,/在專案的WEB-INF/classes目錄下
注意: 無論是java專案還是web專案,在開發時如果把資原始檔放在src下,那麼src下的檔案都會拷貝到類路徑的根目錄下。
回顧重點內容:
mysql加強:
資料約束:
預設值: default 預設值
唯一: unique
非空: not null
主鍵:primary key (唯一+非空 )
自增長: auto_increment
外來鍵: foreign key
級聯操作:
級聯更新: on update cascade
級聯刪除: on delete cascade
多表查詢:
1)內連線查詢: inner join
作用: 當兩種表滿足了連線條件時的資料才會顯示。
2)左外連線: left outer join
作用:左表完全顯示。右表的資料如果滿足了連線條件,則顯示對應的資料,如果不滿 足條件,那麼顯示null。
3)右外連線: right outer join
作用:右表完全顯示。左表的資料如果滿足了連線條件,則顯示對應的資料,如果不滿 足條件,那麼顯示null。
資料庫設計:
第一正規化:要求表的每個欄位都必須獨立的不可分割的最小單元。
第二正規化:要求表的除主鍵外的其他欄位都和主鍵有依賴關係。(一張表表達一個意思)
第三正規化:要求表的除主鍵外的其他欄位都只能由主鍵決定。
今天目標: jdbc基礎
1 jdbc入門
1.1 簡介
使用java程式訪問(操作)資料庫(傳送sql語句),這叫用到了jdbc技術!!!!
1.2 使用java程式訪問資料庫的前提
1)先登入到資料庫:
資料庫的主機地址(ip地址)
埠
資料庫使用者名稱
資料庫使用者密碼
連線的資料庫
2)傳送sql語句
1.3 Jdbc的核心api
|-Driver介面: 驅動程式介面。
|-Connection connect() 用於連線資料庫的方法
可以使用驅動程式管理類獲取連線:
DriverManager.getConnection(url,user,pasword);