三、數據庫設計
1_簡介
1.數據庫設計設計什么?
有哪些表
表里有哪些字段
表和表之間是什么關系
2.表關系有哪幾種?
一對一
一對多(多對一)
多對多
2_多表關系實現
表關系之一對多
一對多 (多對一):
如:部門表和員工表
一個部門對應多個員工,一個員工對應一個部門
實現方式:在多的一方建立外鍵,指向一的一方的主鍵
表關系之多對多
多對多:
如:訂單和商品
一個商品對應多個訂單,一個訂單包含多個商品
實現方式:建立第三張中間表,中間表至少包含兩個外鍵,分別關聯兩方主鍵
表關系之一對一
一對一:
如:用戶和用戶詳情
一對一關系多用于表拆分,將一個實體中經常使用的字段放一張表,不經常使用的字段放另一張表,用于提升查詢性能
實現方式:在任意一方加入外鍵,關聯另一方主鍵,并且設置外鍵為唯一 (UNIQUE)
四、多表查詢
1_簡介
多表查詢
笛卡爾積:取 A,B 集合所有組合情況
多表查詢:從多張表查詢數據
?? ?連接查詢
?? ??? ?內連接:相當于查詢 A B 交集數據
?? ??? ?外連接:
?? ??? ??? ?左外連接:相當于查詢 A 表所有數據和交集部分數據
?? ??? ??? ?右外連接:相當于查詢 B 表所有數據和交集部分數據
?? ?子查詢
2_內連接&外連接
內連接
內連接查詢語法
-- 隱式內連接
SELECT 字段列表 FROM 表1,表2... WHERE 條件; ?
-- 顯式內連接
SELECT 字段列表 FROM 表1 [INNER] JOIN 表2 ON 條件; ?
內連接相當于查詢 A B 交集數據
外連接
外連接查詢語法
-- 左外連接 ?
SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 ON 條件; ?
-- 右外連接 ?
SELECT 字段列表 FROM 表1 RIGHT [OUTER] JOIN 表2 ON 條件; ?
左外連接:相當于查詢 A 表所有數據和交集部分數據
右外連接:相當于查詢 B 表所有數據和交集部分數據
3_子查詢
子查詢
1.子查詢概念:
查詢中嵌套查詢,稱嵌套查詢為子查詢
2.子查詢根據查詢結果不同,作用不同:
單行單列
多行單列
多行多列
單行單列:作為條件值,使用 = != > < 等進行條件判斷
SELECT 字段列表 FROM 表 WHERE 字段名 = (子查詢); ?
多行單列:作為條件值,使用 in 等關鍵字進行條件判斷
SELECT 字段列表 FROM 表 WHERE 字段名 in (子查詢); ?
多行多列:作為虛擬表
SELECT 字段列表 FROM (子查詢) WHERE 條件; ?
五、事務
簡介四大特征
事務簡介
數據庫的事務(Transaction)是一種機制、一個操作序列,包含了一組數據庫操作命令
事務把所有的命令作為一個整體一起向系統提交或撤銷操作請求,即這一組數據庫命令要么同時成功,要么同時失敗
事務是一個不可分割的工作邏輯單元
事務四大特征
原子性(Atomicity):事務是不可分割的最小操作單位,要么同時成功,要么同時失敗
一致性(Consistency):事務完成時,必須使所有的數據都保持一致狀態
隔離性(Isolation):多個事務之間,操作的可見性
持久性(Durability):事務一旦提交或回滾,它對數據庫中的數據的改變就是永久的
MySQL 事務默認自動提交
-- 查看事務的默認提交方式 ?
SELECT @@autocommit; ?
-- 1 自動提交 ?0 手動提交 ?
-- 修改事務提交方式 ?
set @@autocommit = 0; ?
六、JDBC
1_簡介
JDBC 概念:
JDBC 就是使用 Java 語言操作關系型數據庫的一套 API
全稱: (Java DataBase Connectivity) Java 數據庫連接
JDBC 本質:
官方 (sun 公司) 定義的一套操作所有關系型數據庫的規則,即接口
各個數據庫廠商去實現這套接口,提供數據庫驅動 jar 包
我們可以使用這套接口 (JDBC) 編程,真正執行的代碼是驅動 jar 包中的實現類
JDBC 好處:
各數據庫廠商使用相同的接口,Java 代碼不需要針對不同數據庫分別開發
可隨時替換底層數據庫,訪問數據庫的 Java 代碼基本不變
(右側圖示輔助理解:通過 “MySQL 驅動” 連接 Java 代碼與 MySQL 數據庫 )
2_快速入門
0.創建工程,導入驅動 jar 包
mysql-connector-java-5.1.48.jar
1.注冊驅動
Class.forName("com.mysql.jdbc.Driver");?
這里該類在 MySQL Connector/J 8.0 之后已被棄用,新版本推薦使用?com.mysql.cj.jdbc.Driver
2.獲取連接
Connection conn = DriverManager.getConnection(url, username, password); ?
3.定義 SQL 語句
String sql = "update..."; ?
4.獲取執行 SQL 對象
Statement stmt = conn.createStatement(); ?
5.執行 SQL
stmt.executeUpdate(sql); ?
6.處理返回結果
7釋放資源
3_API詳解DriverManager
DriverManager
DriverManager (驅動管理類) 作用:
注冊驅動
獲取數據庫連接
1.注冊驅動
Class.forName("com.mysql.jdbc.Driver");
查看 Driver 類源碼
static {
? ? try {
? ? ? ? DriverManager.registerDriver(new Driver());
? ? } catch (SQLException var1) {
? ? ? ? throw new RuntimeException("Can't register driver!");
? ? }
}
提示:
MySQL 5 之后的驅動包,可以省略注冊驅動的步驟
自動加載 jar 包中 META-INF/services/java.sql.Driver 文件中的驅動類
2.獲取連接
static Connection ? ? ? ? ? ? ? ?getConnection(String url, String user, String password)
參數
1.url:連接路徑
語法:jdbc:mysql://ip地址(域名):端口號/數據庫名稱?參數鍵值對1&參數鍵值對2...
示例:jdbc:mysql://127.0.0.1:3306/db1
細節:
?? ?如果連接的是本機 mysql 服務器,并且 mysql 服務默認端口是 3306,則 url 可以簡寫為:jdbc:mysql:///數據庫名稱?參數鍵值對
?? ?配置 useSSL=false 參數,禁用安全連接方式,解決警告提示
2.user:用戶名
3.password:密碼
4_API詳解Connection
Connection
Connection (數據庫連接對象) 作用:
獲取執行 SQL 的對象
管理事務
1.獲取執行 SQL 的對象
普通執行 SQL 對象
?? ?Statement createStatement()
預編譯 SQL 的執行 SQL 對象:防止 SQL 注入
?? ?PreparedStatement prepareStatement(sql)
執行存儲過程的對象
?? ?CallableStatement prepareCall(sql)
2.事務管理
?? ?MySQL 事務管理
開啟事務:BEGIN; / START TRANSACTION;
提交事務:COMMIT;
回滾事務:ROLLBACK;
MySQL默認自動提交事務
?? ?JDBC 事務管理:Connection 接口中定義了 3 個對應的方法
開啟事務:setAutoCommit(boolean autoCommit):true為自動提交事務;false為手動提交事務,即為開啟事務
提交事務:commit()
回滾事務:rollback()
5_API詳解Statement
Statement
Statement 作用:
執行 SQL 語句
int ?executeUpdate(sql):執行DML、DDL語句 ?
? 返回值: (1) DML語句影響的行數 (2) DDL語句執行后,執行成功也可能返回 0 ?
ResultSet ?executeQuery(sql):執行DQL語句 ?
? 返回值:ResultSet結果集對象 ?
6_API詳解ResultSet
ResultSet
ResultSet (結果集對象) 作用:
封裝了 DQL 查詢語句的結果
ResultSet ?stmt.executeQuery(sql):執行DQL 語句,返回 ResultSet 對象 ?
獲取查詢結果
boolean ?next(): (1) 將光標從當前位置向前移動一行 ?(2) 判斷當前行是否為有效行 ?
返回值: ?
? ? true: 有效行,當前行有數據 ?
? ? false: 無效行,當前行沒有數據 ?
xxx ?getXxx(參數):獲取數據 ?
xxx: 數據類型;如: int getInt(參數);String getString(參數) ?
參數: ?
? ? int: 列的編號,從1開始 ?
? ? String: 列的名稱 ?
使用步驟:
1.游標向下移動一行,并判斷該行否有數據: next ()
2.獲取數據: getXxx (參數)
//循環判斷游標是否是最后一行末尾
while(rs.next()){
? ? //獲取數據
? ? rs.getXxx(參數);
}
package com.itheima.jdbc;import org.junit.Test;import java.sql.*;//JDBC快速入門 public class JDBCDemo7_PreparedStatement {@Testpublic void PreparedStatement() throws Exception {//2. 獲取連接: 如果連接的是本機mysql并且端口是默認的 3306 可以簡化書寫String url = "jdbc:mysql:///test?useSSL=false";String username = "root";String password = "1234";Connection conn = DriverManager.getConnection(url, username, password);// 接收用戶輸入 用戶名和密碼String name = "zhangsan";String pwd = "123";// 定義sqlString sql = "select * from tb_user where username = ? and password = ?";// 獲取pstmt對象PreparedStatement pstmt = conn.prepareStatement(sql);// 設置?的值pstmt.setString(1, name);pstmt.setString(2, pwd);// 執行sqlResultSet rs = pstmt.executeQuery();// 判斷登錄是否成功if(rs.next()){System.out.println("登錄成功~");}else{System.out.println("登錄失敗~");}//7. 釋放資源rs.close();pstmt.close();conn.close();} }
7_API詳解PreparedStatement
PreparedStatement
PreparedStatement 作用:
?? ?預編譯 SQL 語句并執行:預防 SQL 注入問題
SQL 注入
?? ?SQL 注入是通過操作輸入來修改事先定義好的 SQL 語句,用以達到執行代碼對服務器進行攻擊的方法。
① 獲取 PreparedStatement 對象
// SQL語句中的參數值,使用?占位符替代
String sql = "select * from user where username = ? and password = ?";
// 通過Connection對象獲取,并傳入對應的sql語句
PreparedStatement pstmt = conn.prepareStatement(sql);
② 設置參數值
PreparedStatement對象:setXxx(參數1,參數2):給?賦值 ?
Xxx:數據類型;如 setInt(參數1,參數2) ?
參數: ?
?? ?參數1:?的位置編號,從1開始 ?
?? ?參數2:?的值 ?
③ 執行 SQL
executeUpdate(); / executeQuery(); :不需要再傳遞sql ?
PreparedStatement 原理
PreparedStatement 好處:
1.預編譯 SQL,性能更高
2.防止 SQL 注入:將敏感敏感字符進行轉義
① PreparedStatement 預編譯功能開啟: useServerPrepStmts=true
② 配置 MySQL 執行日志 (重啟 mysql 服務后生效)
log-output=FILE ?
general-log=1 ?
general_log_file="D:\mysql.log" ?
slow-query-log=1 ?
slow_query_log_file="D:\mysql_slow.log" ?
long_query_time=2 ?
PreparedStatement 原理:
1.在獲取 PreparedStatement 對象時,將 sql 語句發送給 mysql 服務器進行檢查,編譯(這些步驟很耗時)
2.執行時就不用再進行這些步驟了,速度更快
3.如果 sql 模板一樣,則只需要進行一次檢查、編譯