MySQL數(shù)據(jù)庫?JDBC?編程(Java?連接?MySQL)
1. 數(shù)據(jù)庫編程的基礎(chǔ)條件
如果你想實現(xiàn)代碼操作數(shù)據(jù)庫,那么以下條件是你實現(xiàn)它的前提
編程語言:
例如 Java、C++、Python 等等,這些語言都能夠?qū)崿F(xiàn)操作數(shù)據(jù)庫
某個數(shù)據(jù)庫的操作:
例如我在前面章節(jié)就介紹了關(guān)于 MySQL 的操作,實現(xiàn)其它數(shù)據(jù)庫如 Oracle、SQL Server 等等也要學(xué)會對應(yīng)數(shù)據(jù)庫的一些操作
安裝數(shù)據(jù)庫驅(qū)動包:
不同的數(shù)據(jù)庫對應(yīng)不同的編程語言提供了不同的數(shù)據(jù)庫驅(qū)動包,這些驅(qū)動包內(nèi)實現(xiàn)了操作對應(yīng)數(shù)據(jù)庫的 API
2. Java 的數(shù)據(jù)庫編程:JDBC
由于不同數(shù)據(jù)庫的廠商實現(xiàn)數(shù)據(jù)庫的 API 其實是不太一樣的,因此很多語言就把這些數(shù)據(jù)庫的 API 進(jìn)行再一次的封裝,封裝出了一套統(tǒng)一的 API。這樣就可以通過一套代碼來操作多個不同的數(shù)據(jù)庫了
在 Java 中,這樣的封裝就是由 Java 標(biāo)準(zhǔn)庫來完成的,封裝出了一套統(tǒng)一的數(shù)據(jù)庫 API 稱為 JDBC
拓展:
Java 本身是跨平臺語言,雖然不同操作系統(tǒng)提供了不同的 API,但是 Java 本身也把這些 API 封裝了起來,在標(biāo)準(zhǔn)庫中提供了統(tǒng)一的接口,因此 Java 就可以一次編譯,到處運(yùn)行
JDBC 介紹:
- JDBC,即
Java Database Connectivity
,是指 Java 數(shù)據(jù)庫連接。是一種用于執(zhí)行 SQL 語句的Java API
,它是 Java 中的數(shù)據(jù)庫連接規(guī)范。 - 這個 API 由
java.sql
和javax.sql
包中的一些類和接口組成,它為 Java 開發(fā)人員操作數(shù)據(jù)庫提供了一個標(biāo)準(zhǔn)的 API,可以為多種關(guān)系數(shù)據(jù)庫提供統(tǒng)一訪問
注意:
- JDBC API 是 Java 標(biāo)準(zhǔn)庫自帶的,可以直接用,但是 MySQL 的 JDBC 驅(qū)動不是系統(tǒng)自帶的,因此需要額外進(jìn)行下載安裝
- MySQL 的 JDBC 驅(qū)動其實就是對 JDBC API 里面一些類和接口的具體實現(xiàn)
3. JDBC 訪問數(shù)據(jù)庫的層次結(jié)構(gòu)
4. MySQL 數(shù)據(jù)庫操作介紹
在前面章節(jié)我就介紹了關(guān)于 MySQL 的一些知識了,如果你在這方面有漏洞的話,可以直接通過下面的文章來進(jìn)行補(bǔ)充。
第一章鏈接: 【MySQL 數(shù)據(jù)庫】數(shù)據(jù)庫的基礎(chǔ)知識
第二章鏈接: 【MySQL 數(shù)據(jù)庫】MySQL 的對庫的操作及其數(shù)據(jù)類型
第三章鏈接: 【MySQL 數(shù)據(jù)庫】數(shù)據(jù)表的基本操作
第四章鏈接: 【MySQL 數(shù)據(jù)庫】數(shù)據(jù)庫的約束及數(shù)據(jù)表的設(shè)計原理
第五章鏈接: 【MySQL 數(shù)據(jù)庫】聚合查詢和聯(lián)合查詢操作
第六章鏈接: 【MySQL 數(shù)據(jù)庫】MySQL 的索引和事務(wù)
5. MySQL 驅(qū)動包的下載及添加到項目
由于 MySQL 的 JDBC 驅(qū)動不是系統(tǒng)自帶的,因此需要額外進(jìn)行下載安裝
各大數(shù)據(jù)庫的官網(wǎng)就有對應(yīng)數(shù)據(jù)庫的 JDBC 驅(qū)動,但這里我推薦使用一些中央倉庫來進(jìn)行下載,例如 mvnrepository
驅(qū)動包下載步驟:
進(jìn)入 mvnrepository 網(wǎng)站,在搜索欄搜索 MySQL,就可以查詢到以下結(jié)果
選擇第一個 MySQL Connector/J,就可以跳轉(zhuǎn)到下載版本選擇的頁面
選擇好自己對應(yīng)的數(shù)據(jù)庫版本的驅(qū)動(大版本一定要對應(yīng),小版本區(qū)別不大可以隨意選),由于我自己是 5.x 系列的MySQL,因此,我選擇大版號是5的就行。選擇后就跳到了最終下載的頁面
點擊 jar 就開始下載了(這個 jar 包就是將這個驅(qū)動包中的一些 .class 文件以壓縮包的形式進(jìn)行打包了)
下載完成后,這個驅(qū)動包就已經(jīng)下載到你本地了,只再將它引入到你的項目就可以是用
6. JDBC 使用步驟
6.1 創(chuàng)建數(shù)據(jù)庫源,連接 Connection
創(chuàng)建一個數(shù)據(jù)庫源:
DataSource dataSource=new MysqlDataSource(); // DataSource 是來自于 Java 標(biāo)準(zhǔn)庫的一個接口,它用來表示“數(shù)據(jù)庫在哪” // MysqlDataSource 是來自于 MySQL 的驅(qū)動包,它是實現(xiàn)了 DataSource 接口的類
數(shù)據(jù)庫就是一個服務(wù)器程序,可以通過 DataSource
來描述服務(wù)器的 地址、端口、用戶名、密碼、要訪問的數(shù)據(jù)庫名等
把數(shù)據(jù)庫的位置信息,設(shè)置到 DataSource
中
// 1)通過一個 URL 來表示連接的數(shù)據(jù)庫、數(shù)據(jù)庫的 ip、端口、數(shù)據(jù)庫名、編碼方式、是否加密 ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&setSSL=false"); // 2)設(shè)置登錄數(shù)據(jù)庫的用戶名 ((MysqlDataSource)dataSource).setUser("root"); // 3)設(shè)置登錄數(shù)據(jù)庫的密碼 ((MysqlDataSource)dataSource).setPassword("1234");
由于 setURL
、setUser
、setPassword
都是 MysqlDataSource
實現(xiàn)的,所以使用時需要向下轉(zhuǎn)型
上述 URL 是一種固定的寫法,例如:jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&setSSL=false
- jdbc 表示使用 JDBC 訪問數(shù)據(jù)庫
- mysql 表示訪問的數(shù)據(jù)庫是 MySQL
- 172.0.0.1 是 IP 地址,IP 地址是用來區(qū)分是哪個主機(jī),172.0.0.1 這個 IP 地址表示當(dāng)前使用的主機(jī)自身,因為我的 MySQL 服務(wù)器也裝在自己電腦上,自行修改
- 3306 是端口號,這是安裝數(shù)據(jù)庫服務(wù)器時手動設(shè)置的,一般默認(rèn)是3306,它是用來區(qū)分主機(jī)上的某個程序
- test 是要訪問的數(shù)據(jù)庫名,這是我數(shù)據(jù)庫里面的,自行修改
characterEncoding=utf8
是用來指定編碼方式的,此處是使用 utf8,需要和使用的數(shù)據(jù)庫便方式對應(yīng),自行修改useSSL=false
是用來表示是否加密的,此處表示不加密,自行修改
連接數(shù)據(jù)庫,進(jìn)行真正的網(wǎng)絡(luò)通信:
Connection connection=dataSource.getConnection();
Connection
是 Java 標(biāo)準(zhǔn)庫里的,雖然 MySQL 驅(qū)動里面也有。它是用來進(jìn)行和數(shù)據(jù)庫服務(wù)器進(jìn)行網(wǎng)絡(luò)連接的
getConnection 用于獲得試圖建立到指定數(shù)據(jù)庫 URL 的連接,如果連接成功就返回一個 Connection
對象,如果失敗就拋出異常
由于 getConnection
可能會連接失?。ɡ?IP 地址、端口等輸入錯誤),因此就需要在方法聲明時通過 throws 給上層調(diào)用者拋出異常或者使用 try-catch
去處理異常
6.2 構(gòu)造 SQL 語句,為執(zhí)行的操作做準(zhǔn)備
通過字符串,構(gòu)造一個要執(zhí)行的 sql
// 例如要執(zhí)行新增元素操作(表名為 student,有兩列 id 和 student Scanner scanner=new Scanner(System.in); System.out.print("請輸入 id:"); int id=scanner.nextInt(); System.out.print("請輸入 姓名:"); String name=scanner.next(); String sql="insert into student values(?,?)";
- sql 就是構(gòu)造的 SQL 語句,里面就是要執(zhí)行的具體操作
- sql 語句中可以不用加分號
- 表示通配符,可以通過它對 sql 語句里的內(nèi)容進(jìn)行動態(tài)替換,需要替換的內(nèi)容用 ?代替,后續(xù)再使用 PreparedStatement 對象的一些方法將其再替換成具體要更改的值
例如:
void setInt(int paramenterIndex, int x)
:paramenterIndex 表示 sql 語句中要替換通配符的具體位置(從1開始),x 表示要替換掉具體值void setString(int parameterIndex, String x)
:paramenterIndex 表示 sql 語句中要替換通配符的具體位置(從1開始),x 表示要替換掉具體值
通過 prepareStatement(sql) 方法,將構(gòu)造的字符串 sql 轉(zhuǎn)化成真正的數(shù)據(jù)庫底層的 SQL 語句
PreparedStatement statement=connection.prepareStatement(sql); // 通過 setInt 方法,將 SQL 語句中的第一處通配符進(jìn)行具體值的替換 statement.setInt(1,id); // 通過 setString 方法,將 SQL 語句中的第二處通配符進(jìn)行具體值的替換 statement.setString(2,name);
JDBC 中,使用 Connection 和數(shù)據(jù)庫建立了連接對象 connection
,那么 connection
就可以調(diào)用 prepareStatement(String sql) 方法對參數(shù) sql 指定的 SQL 語句進(jìn)行編譯預(yù)處理,生成該數(shù)據(jù)庫底層的內(nèi)部命令,并將該命令封裝在 PreparedStatement 對象中
6.3 執(zhí)行 SQL,并處理結(jié)果集
通過 PreparedStatement
對象的 executeQuery
或者 executeUpdate 方法來執(zhí)行 SQL
如果是執(zhí)行內(nèi)容變更的操作(增加、修改、刪除),就使用 int executeUpdate() 方法
int ret=statement.executeUpdate(); // executeUpdate 的返回結(jié)果是執(zhí)行該操作后影響的行數(shù) // 可以通過打印返回值來顯示影響的行數(shù) System.out.println("ret: "+ret);
如果要是要執(zhí)行查詢操作,就使用 ResultSet executeQuery() 方法
ResultSet resultSet=statement.executeQuery(); // executeQuery 的返回結(jié)果是執(zhí)行該操作后查詢到的類似于臨時表的結(jié)構(gòu),存放在 ResultSet 對象中 // 接下來我們可以對它進(jìn)行遍歷,類似于迭代器的遍歷,方法如下 while(resultSet.next()){ // 假設(shè)有兩列 id 和 name int id=resultSet.getInt(id); String name=resultSet.getString(name); System.out.println("id="+id+", name="+name); }
SQL 查詢語句對數(shù)據(jù)庫的查詢操作將返回一個 ResultSet
對象,ResultSet
對象由按列(字段)組織的數(shù)據(jù)行構(gòu)成
ResultSet 對象一次只能看到一行數(shù)據(jù),使用 next() 方法,可以移到下一個數(shù)據(jù)行(類似于 i++)
可以使用 ResultSet
對象的 getXxx()
方法,去獲得字段。常用方法后面講將介紹
6.4 釋放資源
當(dāng)我們執(zhí)行完了我們的 SQL 語句后,如果不再使用某些對象,就需要把連接關(guān)閉,釋放掉對應(yīng)的資源
// 如果有 ResultSet 對象不需要使用后,需要關(guān)閉這個連接 resultSet.close(); // Connection 不需要使用后,需要關(guān)閉這個連接 connection.close(); // PreparedStatement 不需要使用后,需要關(guān)閉這個連接 statement.close();
ResultSet
、Connection
、PreparedStatement
這些對象都對應(yīng)著一些及機(jī)器的硬件資源,如果不使用的話就要及時還回去。就類似于借書,如果大家在圖書館只借書,不還書,那么圖書館的書籍資源就會一直減少
這些對象可以使用 close()
方法,來關(guān)閉和客戶端與服務(wù)器建立的連接,以此釋放占用的資源
6.5 JDBC 編程模板
通過上面五步,就可以進(jìn)行基礎(chǔ)的 Java 的 JDBC 編程了,雖然方法不止這一種,但如果你還不會的話,掌握這個方法就行了。最后再總結(jié)下整個的模板,依據(jù)它,我們就可以用 Java 語言對 MySQL 數(shù)據(jù)庫進(jìn)行各種操作
public static void test(){ // 1. 創(chuàng)建數(shù)據(jù)庫源,連接 Connection DataSource dataSource=new MysqlDataSource(); ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false"); ((MysqlDataSource)dataSource).setUser("root"); ((MysqlDataSource)dataSource).setPassword("1234"); Connection connection=dataSource.getConnection(); // 2. 構(gòu)造一個 SQL 語句,為要進(jìn)行的操作做準(zhǔn)備 String sql=""; PreparedStatement statement=connection.prepareStatement(sql); // 3. 執(zhí)行 SQL,并處理結(jié)果集 int ret=statement.executeUpdate(); // 4. 執(zhí)行完成,釋放資源 statement.close(); connection.close(); }
7. JDBC 常用接口和類
上述 JDBC 編程步驟中已經(jīng)將以下接口和類介紹了很多,所以可以互相補(bǔ)充漏洞
7.1 DataSource 和 MysqlDataSource
補(bǔ)充:
上述代碼也可以直接使用 MysqlDataSource
來創(chuàng)建一個數(shù)據(jù)源,這樣就可以不用使用向下轉(zhuǎn)型了。但是如果使用 DataSource 的話,那么代碼中其它代碼其實都是使用 DataSource
這個類型的,這是和具體數(shù)據(jù)庫類型無關(guān)的類,當(dāng)你需要切換數(shù)據(jù)庫時,就不需要大幅度修改代碼
7.2 Connection
Connection
接口實現(xiàn)類由數(shù)據(jù)庫提供,獲取 Connection
對象通常有兩種方式:
方式一: 通過 DataSource(數(shù)據(jù)源)對象獲取
// 創(chuàng)建一個數(shù)據(jù)庫源 DataSource dataSource=new MysqlDataSource(); // 設(shè)置數(shù)據(jù)庫具體信息 ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false"); ((MysqlDataSource)dataSource).setUser("root"); ((MysqlDataSource)dataSource).setPassword("1234"); // 創(chuàng)建數(shù)據(jù)庫連接 Connection connection=dataSource.getConnection();
方式二: 通過 DriverManager
(驅(qū)動管理類)的靜態(tài)方法獲取
// 加載 JDBC 驅(qū)動程序 Class.forName("com.mysql.cj.jdbc.Driver"); // 創(chuàng)建數(shù)據(jù)庫連接 Connection connection=DriverManager.getConnection(url);
MySQL 數(shù)據(jù)庫驅(qū)動程序被封裝在 Driver
類中,該類的包名是 com.mysql.cj.jdbc
,該類不是 Java 運(yùn)行環(huán)境類庫中的類
上述兩種方式的區(qū)別:
DriverManager
類來獲取的Connection
連接,是無法重復(fù)利用的,每次使用完以后釋放資源時,通過connection.close()
都是關(guān)閉物理連接DataSource
提供連接池的支持。連接池在初始化時創(chuàng)建一定數(shù)量的數(shù)據(jù)庫連接,這些連接是可以重復(fù)利用的,每次使用完數(shù)據(jù)庫連接,通過connection.close()
釋放資源,都是將Connection
連接對象回收
7.3 PreparedStatement
PreparedStatement
是 JDBC API 提供的三種可以將 SQL 語句發(fā)送到數(shù)據(jù)庫的對象之一。這里對這三種做一個簡單介紹
Statement
: 用于執(zhí)行不帶參數(shù)的簡單 SQLPreparedStatement
:
- 用于執(zhí)行帶或者不帶參數(shù)的 SQL 語句
- SQL 語句會預(yù)編譯在數(shù)據(jù)庫系統(tǒng)
- 執(zhí)行速度快于 Statement 對象
CallableStatement
: 用于執(zhí)行數(shù)據(jù)庫存儲過程的調(diào)用
7.4 ResultSet
ResultSet
對象它被稱為結(jié)果集,它代表符合 SQL 語句條件的所有行,并且它通過一套 getXxx() 方法提供了對這些行中數(shù)據(jù)的訪問
ResultSet 里的數(shù)據(jù)是一行一行排列的,每當(dāng)有多個字段,并且有一個記錄指針,指針?biāo)傅臄?shù)據(jù)行叫做當(dāng)前數(shù)據(jù)行,我們只能來操作當(dāng)前的數(shù)據(jù)行。我們?nèi)绻胍〉媚骋粭l記錄,就要使用 ResultSet
的 next()
方法,可以通過結(jié)合 while 循環(huán)來遍歷 ResultSet 里的所有記錄
常見 ResultSet 對象方法:
注意:
ResultSet 對象和數(shù)據(jù)庫連接對象 Connection 實現(xiàn)了緊密連接,一旦連接對象被關(guān)閉,ResultSet 對象中的數(shù)據(jù)就會立刻消失
8. Java 操作數(shù)據(jù)庫實例
8.1 往表中新增數(shù)據(jù)
在 student 表中新增學(xué)生 id 和 name:
public static void testInsert() throws SQLException { DataSource dataSource=new MysqlDataSource(); ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false"); ((MysqlDataSource)dataSource).setUser("root"); ((MysqlDataSource)dataSource).setPassword("1234"); Connection connection=dataSource.getConnection(); Scanner scanner=new Scanner(System.in); System.out.print("請輸入id:"); int id=scanner.nextInt(); System.out.print("請輸入姓名:"); String name=scanner.next(); String sql="insert into student values(?,?)"; PreparedStatement statement=connection.prepareStatement(sql); statement.setInt(1,id); statement.setString(2,name); int ret=statement.executeUpdate(); System.out.println("ret: "+ret); statement.close(); connection.close(); }
8.2 刪除表中的數(shù)據(jù)
在表名為 student 的表中,刪除學(xué)生表中符合 id 條件的記錄:
public static void testDelete() throws SQLException { DataSource dataSource=new MysqlDataSource(); ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false"); ((MysqlDataSource)dataSource).setUser("root"); ((MysqlDataSource)dataSource).setPassword("1234"); Connection connection=dataSource.getConnection(); Scanner scanner=new Scanner(System.in); System.out.print("請輸入要刪除的 id:"); int id=scanner.nextInt(); String sql="delete from student where id=?"; PreparedStatement statement=connection.prepareStatement(sql); statement.setInt(1,id); int ret=statement.executeUpdate(); System.out.println("ret: "+ret); statement.close(); connection.close(); }
8.3 修改表中的數(shù)據(jù)
在表名為 student 的表中,將符合 id 條件的學(xué)生姓名進(jìn)行修改:
public static void testUpdate() throws SQLException { DataSource dataSource=new MysqlDataSource(); ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false"); ((MysqlDataSource)dataSource).setUser("root"); ((MysqlDataSource)dataSource).setPassword("1234"); Connection connection=dataSource.getConnection(); Scanner scanner=new Scanner(System.in); System.out.print("情輸入你要更改的學(xué)生 id:"); int id=scanner.nextInt(); System.out.print("請輸入你要更改后的學(xué)生姓名:"); String name=scanner.next(); String sql="update student set name=? where id=?"; PreparedStatement statement=connection.prepareStatement(sql); statement.setString(1,name); statement.setInt(2,id); int ret=statement.executeUpdate(); System.out.println("ret: "+ret); statement.close(); connection.close(); }
8.4 查找表中的數(shù)據(jù)
查找表名為 student 的表中的所有數(shù)據(jù):
public static void testSelect() throws SQLException { DataSource dataSource=new MysqlDataSource(); ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false"); ((MysqlDataSource)dataSource).setUser("root"); ((MysqlDataSource)dataSource).setPassword("1234"); Connection connection=dataSource.getConnection(); String sql="select * from student"; PreparedStatement statement=connection.prepareStatement(sql); ResultSet resultSet=statement.executeQuery(); while(resultSet.next()){ int id=resultSet.getInt("id"); String name=resultSet.getString("name"); System.out.println("id = "+id+", name = "+name); } resultSet.close(); statement.close(); connection.close(); }
到此這篇關(guān)于MySQL數(shù)據(jù)庫 JDBC 編程(Java 連接 MySQL)的文章就介紹到這了,更多相關(guān)Java 連接 MySQL內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL中使用FREDATED引擎實現(xiàn)跨數(shù)據(jù)庫服務(wù)器、跨實例訪問
這篇文章主要介紹了MySQL中使用FREDATED引擎實現(xiàn)跨數(shù)據(jù)庫服務(wù)器、跨實例訪問,本文講解了FEDERATED存儲引擎的描述、安裝與啟用FEDERATED存儲引擎、準(zhǔn)備遠(yuǎn)程服務(wù)器環(huán)境等內(nèi)容,需要的朋友可以參考下2014-10-10Mysql大數(shù)據(jù)量查詢優(yōu)化思路詳析
這篇文章主要介紹了Mysql大數(shù)據(jù)量查詢優(yōu)化思路,Mysql大表查詢優(yōu)化,理論上千萬級別以下的數(shù)據(jù)量Mysql單表查詢性能處理都是可以的。下文我們就來看看具體得思路解析2022-01-01Mysql中TIMESTAMPDIFF函數(shù)的語法與練習(xí)案例
在應(yīng)用時經(jīng)常要使用這兩個函數(shù)TIMESTAMPDIFF和TIMESTAMPADD,下面這篇文章主要給大家介紹了關(guān)于Mysql中TIMESTAMPDIFF函數(shù)的語法與練習(xí)案例的相關(guān)資料,需要的朋友可以參考下2022-09-09mysql 5.7.17 安裝配置方法圖文教程(windows)
這篇文章主要為大家分享了mysql 5.7.17 安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01