目錄
- 前言
- 一、資料庫程式設計必備條件
- 二、下載下傳導入驅動包jar包
- 三、JDBC程式設計(在IDEA中使用)
-
-
- 1. 建立資料源對象
- 2. 讓代碼和資料庫伺服器建立連接配接
- 3. 構造要執行的SQL語句+ 預處理【構造請求】
- 4. 執行sql:執行sql【發送請求,讀取響應】
- 5. 周遊結果集(隻針對executeQuery)
- 6. 完成之後,關閉釋放相關資源
- 【相關補充】
-
- 四、面試問題
- 五、參考代碼
- 六、另
- THINK
前言
慢慢來吧 慢慢相遇吧!
主要是介紹 JDBC 的使用以及模闆。
一、資料庫程式設計必備條件
-
咱們的各種資料庫都會提供API,以此來友善程式設計語言的控制
(API:Application Programming Interface 應用程式程式設計接口:提供了一組類/方法供程式員使用)
-
不同種類的資料庫提供的API不一樣,這就會帶來以下問題:
① 程式員需要掌握多種不同的資料庫API,提高了學習成本;
② 如果一個項目要把資料庫替換成另外一種,此時改動就很大
- java中為了解決上述問題,就提供了一組統一風格的資料庫操作API,然後讓這些資料庫廠商來适配java的API;由此,掌握這一套java的API就能夠操作各種資料庫了。這一套java的API就叫做JDBC
- 在JDBC和各種資料庫之間有一個驅動包(一組代碼),該驅動包完成的是:資料庫的原生API到JDBC API之間的轉換。這個轉換API的過程,在計算機屬于中稱為“适配(adapt)”
- 既然需要有驅動包進行接口之間的轉換,那麼就需要先把驅動包下載下傳下來 并 導入到項目中
- 是以,資料庫程式設計必備條件:程式設計語言、資料庫、資料庫驅動包。
二、下載下傳導入驅動包jar包
-
如何下載下傳驅動包jar包?
①Oracle官網;
②中央倉庫:中央倉庫
(注意:安裝時要和資料庫伺服器版本對得上——指的是大版本對應就行)
- .jar包本質上是一個壓縮檔案,類似于 .rar , .zip; 然後點進去jar包發現有很多.class檔案,.jar包其實就是java程式釋出的一種常見手段。
-
如何在項目中導入已經下載下傳好的jar包?
① 先建立一個目錄,與src同級(點的是directory);
② 把下載下傳好的jar包拷貝到該目錄下;
③ 右鍵新建立好的目錄,然後選擇 Add as Library… -->為了使IDEA能夠識别目錄中的jar包
三、JDBC程式設計(在IDEA中使用)
(通過java來操作資料庫)
1. 建立資料源對象
資料源對象就描述了要通路的資料庫是啥,在哪兒。
// 注意:DataSource 是接口,不能直接new
// DataSource來自于标準庫JDBC中的一個接口
// MysqlDataSource 來自于mysql驅動包(是 DataSource 實作的一個類)
① 每種資料庫都會提供對應的類來實作DataSource接口,也就是實作了向上轉型(父類引用指向子類執行個體)
② 該代碼其實就使用了“多态”。多态,可以認為就是“封裝”的更進一步:封裝是把實作細節隐藏起來讓調用者不必考慮具體實作細節而可以直接使用,降低了調用者的使用成本和學習負擔; 多态則是把實作類的類型也隐藏起來,調用者不僅不必考慮細節,連其具體類型也不用考慮,調用者考慮的資訊就更少了。
// 向下轉型(子類引用指向父類執行個體) // setURL
操作不是DataSource裡面的,而是MysqlDataSource裡面的,是以要把父類執行個體轉為子類引用才能調用這個方法。
③ DataSource是服務于各種資料庫的,而MysqlDataSource隻服務于MySQL。
④ MySQL是一個用戶端/伺服器的程式,描述伺服器的位置會使用URL這個概念來表示,而URL是擷取網絡上的資源; 但是有些資料庫如SQLite就不是用戶端/伺服器結構,也就談不上URL。是以,DataSource考慮到通用性就不能使用父類直接來進行調用,而是向下轉型為子類各自調用。
dataSource.setURL();
// 這種寫法也是完全ok的,這是沒有使用多态的寫法
//這種寫法可能會讓MysqlDataSource這個類型出現在很多地方,導緻MySQL和項目耦合性就提高了;如果之後要換成其他資料庫,就需要把所有出現MysqlDataSource這個類型的地方都進行修改。
⑤ 而使用多态,結合向上轉型、向下轉型的寫法,則MysqlDataSource這個類型就隻會出現一次,如果需要進行資料庫的更換,改動就比較小;Mysql和項目的耦合性較低。
耦合性:一個大的程式裡面包含很多個部分,這些部分之間關聯性比較強則耦合性高;關聯性比較低則耦合性較低
内聚:簡單說就是把有關聯的代碼寫到一起,不要到處亂寫
⑥ URL:(Uniform Resource Location)唯一資源定位符,其實就是我們平時說的“網址”。(注意:需要使用 引号 來指明位址)
其實就是:
jdbc:mysql://伺服器位址:端口/資料庫名?參數名=參數值
如:
" jdbc:mysql://127.0.0.1:3306/testbit?character=utf8&useSSL=false"
① jdbc:mysql: 協定名稱
② 127.0.0.1:IP位址:描述了網絡上的一個主機位置,和日常所說的“位址”差不多;而127.0.0.1又是一個特殊的IP位址,表示本機IP! (即:無論本機IP是啥,都可以使用127.0.0.1表示自己的IP位址,類似于this——這叫環回IP
(注: 目前資料庫(外面自己寫的代碼,不是那個黑色框)和伺服器(安裝好的 “服務” 裡的 mysql 就是))都是在自己的電腦上,是以直接使用本機IP就行)
③ 3306:端口号:用來區分主機上的不同應用程式的(安裝資料庫的時候有個環節是配置端口号的,預設就是3306 )
④ testbit:就是要通路的資料庫
⑤ character=utf8:用戶端使用的字元集,要和伺服器這邊一緻
⑥ &useSSL=false:是否加密:true是加密,false是不加密
⑦ DataSource就描述了能夠找到資料庫的資料;URL裡面展現的是資料庫伺服器的位置以及資料庫的名字
⑧ 在已知别人的IP位址時也不一定能夠通路其資料庫:
要保證其他電腦的IP可達;
即使IP可達,也要保證端口可通路;
資料庫要配置成允許其他用戶端通路
((MysqlDataSource)dataSource).setUser(“root”);
((MysqlDataSource)dataSource).setPassword(“密碼”);
// 即使mysql沒有設定密碼也要寫,但是寫成空字元串就行
-----以上描述的是資料在哪
下面要開始通路:通路的時候要先和資料庫伺服器建立連接配接,然後再進行後續操作。
2. 讓代碼和資料庫伺服器建立連接配接
Connection connection = dataSource.getConnection();
// 此時可能會抛出異常,進行throws 或 try...catch
① 注:受查異常(出現異常則必須顯式處理 throws try…catch…) 、 非受查異常
② 使用Connection來表示連接配接;Connection應該使用JDBC裡的Connection(也就是标準庫java.sql裡的Connection),而不是MYSQL驅動包裡的Connection
③(抛出異常中顯示 Access denied 表示使用者名或密碼錯誤)
④ 那我的電腦沒有插網線也沒連WiFi,為啥還是能夠連接配接成功?
——因為mysql的用戶端和伺服器是在同一個主機上的,是通過127.0.0.1 環回IP來連接配接的,與外面連不連接配接網絡沒關系。
3. 構造要執行的SQL語句+ 預處理【構造請求】
String sql = “insert into 表名 values(....值)”;
// 注意雙引号中使用單引号
PreparedStatement statement = connection.preparedStatement(sql);
// 注:有時自己輸入時可能需要占位符? 以及setXXX
① sql語句發給資料庫,資料庫就得對這個SQL語句進行解析(可以了解為編譯);這個解析過程其實是比較消耗時間、消耗資源的;資料庫伺服器日理萬機,要處理很多用戶端的請求,如果把所有的工作都讓伺服器來完成就會讓系統資源更加緊張。
② 是以就使用 PreparedStatement 進行預處理。
③ 注:utf8mb4是mysql獨有的操作,抛開mysql配置檔案其他地方見不到;是以 統一寫做 utf8
4. 執行sql:執行sql【發送請求,讀取響應】
① 執行方法有兩個:executeUpdate對應插入、删除、修改語句 ——傳回一個int,也就是受影響的行數。
② executeQuery對應查詢——傳回值則是臨時表資料,類型是ResultSet結果集。
5. 周遊結果集(隻針對executeQuery)
6. 完成之後,關閉釋放相關資源
statement.close();
connection.close(); // 釋放的是記憶體資源和一些軟體資源
① 之前的statement語句對象和connection連接配接對象,都是需要消耗資源的; 我們常說的資源,主要是一些硬體資源(有時候也指軟體資源)
② 很多操作都是要消耗資源的,比如new一個對象就要消耗一定的資源(這裡是記憶體資源)。
③ 那麼為什麼之前的對象沒有手動釋放呢?
——Java内置了 垃圾回收GC機制 幫我們自動釋放
④【釋放資源的順序要和申請資源的順序正好相反!
先建立的後釋放,後建立的先釋放】
【如果希望使用者在程式運作的時候可以自己輸入資料進行插入,怎麼辦呢?】
—— 字元串拼接方式:如 ’ " + name+ " ’ (外面的單引号如果是字元串形式就需要加) 這樣的形式。
但是該方式存在一些弊端:①代碼非常亂,不直覺;
②不安全,容意引發SQL諸如漏洞(由于自己輸入,那就可能會存在輸入了一些操作SQL的語句來破壞資料庫。
——是以:不應該手動拼接SQL,而是應該借助PreparedStatement内部提供的SQL拼裝機制,這樣會對拼接的内容進行更嚴格的校驗檢查,避免SQL注入(注:下标從1開始! n代表第n個占位符?))】
【相關補充】
- JDBC優勢:
① Java語言通路資料庫操作完全面向抽象接口程式設計
② 開發資料庫應用不用限定在特定資料庫廠商的API
③ 程式的可移植性大大增強
-
資料庫連接配接Connection
1) Connection接口實作類由資料庫提供,擷取Connection對象通常有兩種方式:
① 一種是通過DriverManager(驅動管理類)的靜态方法擷取:
// 加載JDBC驅動程式
Class.forName("com.mysql.jdbc.Driver");
// 建立資料庫連接配接
Connection connection = DriverManager.getConnection(url);
② 一種是通過DataSource(資料源)對象擷取。實際應用中會使用DataSource對象。
DataSource ds = new MysqlDataSource();
((MysqlDataSource)ds).setUrl("jdbc:mysql://localhost:3306/test");
((MysqlDataSource) ds).setUser("root");
((MysqlDataSource) ds).setPassword("root");
Connection connection = ds.getConnection();
2)這兩種方式的差別是:
① DriverManager類來擷取的Connection連接配接,是無法重複利用的,每次使用完以後釋放資源時,通過connection.close()都是關閉實體連接配接。
② DataSource提供連接配接池的支援。連接配接池在初始化時将建立一定數量的資料庫連接配接,這些連接配接是可以複用的,每次使用完資料庫連接配接,釋放資源調用connection.close()都是将Conncetion連接配接對象回收。
3)和DriveManager相比,還是更推薦使用dataSource:因為
① DriveManager使用了反射。(不到萬不得已不要使用反射,代價有點大; 像一些庫和架構為了做到更好的通用性/相容性,會考慮使用反射)
② DriveManager每次getConnection都會重建立立連接配接,但是dataSource則是可以内置連接配接池,可以達到連接配接複用,提高效率。
(注:池存在的目的就是為了 重複利用資源,達到提高效率的目的。簡單說就是:資源準備好,随時用随時拿)
4)實際開發中其實很少使用jdbc,一般會使用一些 庫/架構來簡化資料庫的操作(如MyBatis)
-
在查詢時:resultSet.getXXX的參數可以是列名,但是同樣是從1開始;建議按照列名來取(加引号)。
(考慮:可讀性 + 列名多情況)
- 不隻是條件查詢,各種查詢如insert + select 、 聚合查詢、聯合查詢、子查詢、合并查詢都是同理
-
Statement對象
Statement對象主要是将SQL語句發送到資料庫中。JDBC API中主要提供了三種Statemen對象:
① Statement:用于執行不帶參數的簡單SQL語句。
② PreparedStatement:用于執行帶或不帶參數的SQL語句; SQL語句會預編譯在資料庫系統; 執行速度快于Statement對象。
③ CallableStatement:用于執行資料庫存儲過程的調用。
-
ResultSet對象:
1)ResultSet對象它被稱為結果集,它代表符合SQL語句條件的所有行,并且它通過一套getXXX方法提供了對這些行中資料的通路。
2)ResultSet裡的資料一行一行排列,每行有多個字段,并且有一個記錄指針,指針所指的資料行叫做目前資料行,我們隻能來操作目前的資料行。
3)我們如果想要取得某一條記錄,就要使用ResultSet的next()方法 ,如果我們想要得到ResultSet裡的所有記錄,就應該使用while循環。
四、面試問題
-
資料庫連接配接有哪些方式?分别有什麼差別?
答:① 兩種連接配接方式:DriverManager(驅動管理類)的靜态方法擷取 + DataSource(資料源)對象擷取。
② 差別:連接配接的重複利用(池) + 釋放資源
-
資料庫Statement和PreparedStatement有什麼差別?
答:①SQL語句帶參數
②預編譯
③執行速度
五、參考代碼
主要模仿模闆。
-
增删改查:
增删改查
- 執行個體:
圖書管理系統
①新增貂蟬同學的借閱記錄:詩經,從2019年9月25日17:50到2019年10月25日17:50
②查詢計算機分類下的圖書借閱資訊
③修改圖書《深入了解Java虛拟機》的價格為61.20
④删除id最大的一條借閱記錄
圖書管理
六、另
- 資料庫特點:高共享、低備援、獨立性高、具有完整性。
- 範式:範式是符合某一種級别的關系模式的集合。關系資料庫中的關系必須滿足一定的要求,滿足不同程度要求的為不同範式。目前關系資料庫有六種範式:第一範式( 1NF )、第二範式( 2NF )、第三範式( 3NF )、 Boyce-Codd 範式( BCNF )、第四範式( 4NF )和第五範式( 5NF )。
1)滿足最低要求的範式是第一範式( 1NF )。
2)在第一範式的基礎上進一步滿足更多要求的稱為第二範式( 2NF ),其餘範式以次類推
3)一般說來,資料庫隻需滿足**第三範式( 3NF )**就行了。
① 第一範式:主屬性(主鍵)不為空且不重複,字段不可再分(存在非主屬性對主屬性的部分依賴)。
② 第二範式:如果關系模式是第一範式,每個非主屬性都沒有對主鍵的部分依賴。
③ 第三範式:如果關系模式是第二範式,沒有非主屬性對主鍵的傳遞依賴和部分依賴。
④ BCNF範式:所有屬性都不傳遞依賴于關系的任何候選鍵。
-
if(條件,表達式1,表達式2);
這裡,如果條件為真(非0),則傳回表達式1;條件為假(0)傳回表達式2
- 在select部分,既有單值列,又有分組函數時,所有出現的單值列必須作為分組列處理;且 分組函數(如:sum/max/min/avg) 隻傳回一個值。
- 記住一句話,當要删除的記錄在資料庫中不存在的時候,是不會報錯的。是以,兩個delete是ok的。
- MySQL實作了四種通信協定:TCP/IP協定、Unix Socket協定、Share Memory協定、Named Pipes協定。
- 排它鎖()X)又稱為寫鎖。共享鎖(S)稱為讀鎖。
THINK
- JDBC使用步驟總結
① 建立資料源對象 DataSource
② 建立連接配接 Connection
③ 構造sql + 預處理PreparedStatement
④ 執行sql (兩種不同的execute)
⑤ ( 如果是select,則需要對結果集進行周遊)
⑥ 釋放資源(逆序釋放!)
- 面試題
- 注意另外所補充的。