JDBC 基本介紹
文章目錄
1. JDBC 概念
JDBC(Java DataBase Connectivity,Java數據庫連接),是一種用於執行 SQL 語句的 Java API ,可以爲多種關係數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。JDBC 提供了一種基準,據此可以構建更高級的工具和接口,使數據庫開發人員能夠編寫數據庫應用程序,同時,JDBC也是個商標名。
概念解釋:
- 定義了一套操作所有關係型數據庫的規則(接口)。
- 不同的 JDBC 實現類由不同的廠商實現(數據庫驅動),提供驅動數據庫的 jar 包。
- 我們可以使用這套 JDBC 編程,正真執行的代碼是驅動 jar 包中的實現類。
2. 快速入門
2.1 建表
首先在MySQL數據庫中準備一個表供後續的所有操作。
-- 創建用戶賬單表
create table account(
id INT PRIMARY KEY AUTO_INCREMENT,
a_name VARCHAR(30),
a_money DOUBLE
);
-- 添加張三、李四的賬戶
insert into account(id,a_name,a_money) values
(1,"張三",1000),
(2,"李四",1000);
2.2 代碼展示
需要提前導入連接數據庫的包,如果沒有,參考這篇教程 MySQL驅動下載。
我這裏用的是 MySQL8.0.17 版本,根據自己數據庫的安裝版本下載對應的驅動。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/**
* JDBC快速入門
* 實現,轉賬操作
*/
public class JdbcDemo {
public static void main(String[] args) throws Exception{
//1. 導入jar包
//2. 註冊驅動:5.0版本後可以省略這一步書寫
Class.forName("com.mysql.cj.jdbc.Driver");
//3. 獲取數據庫連接對象:
//若連接本地默認3306端口數據庫可以簡寫爲jdbc:mysql:///數據庫名?serverTimezone=UTC
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC","root","root");
//4. 定義sql
String sql1 = "update account set a_money = 500 where id = 1";
String sql2 = "update account set a_money = 1500 where id = 1";
//5. 獲取sql的對象 Statement
Statement stmt = conn.createStatement();
//6. 執行sql
int count = stmt.executeUpdate(sql1);
int count2 = stmt.executeUpdate(sql2);
//7. 查看處理結果
System.out.println(count);
System.out.println(count2);
//8. 釋放資源
stmt.close();
conn.close();
}
}
注意:
- mysql 5.0 註冊驅動:com.mysql.jdbc.Driver
- mysql 5.0 連接數據庫:jdbc:mysql://localhost:3306/demo_test
- mysql 8.0 註冊驅動:com.mysql.cj.jdbc.Driver
- mysql 8.0 連接數據庫:jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC
3. JDBC 中各個對象
這裏簡單介紹幾個常用管理對象,具體參照 API 中的介紹。
對象 | 功能 | API介紹 |
---|---|---|
DriverManager | 與驅動程序建立連接 | DriverManager 的API介紹 |
Connection | 提供創建語句以及管理連接及其屬性的方法 | Connection 的API介紹 |
Statement | 執行sql的對象,用於發送基本的SQL語句。 | Statement 的API介紹 |
PreparedStatement | 執行sql對象,用於發送準備好的語句或基本的SQL語句 | PreparedStatement 的API介紹 |
ResultSet | 檢索和更新查詢結果 | ResultSet 的API介紹 |
3.1 DriverManager
用於管理一組JDBC驅動程序的基本服務。
方法 | 描述 |
---|---|
static Connection getConnection(String url, String user, String password) | 嘗試建立到給定數據庫URL的連接。 |
參數解釋:
- url:指定連接的路徑:jdbc:mysql://ip地址(域名):端口號/數據庫名稱
- 如果連接的是本機 MySQL 服務器,並且 MySQL 服務器默認端口是 3306,則 url 可以簡寫爲:jdbc:mysql:///數據庫名稱 。
- user:數據庫連接用戶名
- password:數據庫連接密碼
代碼應用片段:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC","root","root");
3.2 Connection
與特定數據庫的連接(會話)。執行SQL語句,並在連接的上下文中返回結果。
方法 | 描述 |
---|---|
Statement createStatement() | 創建一個Statement對象,用於將SQL語句發送到數據庫。 |
PreparedStatement prepareStatement(String sql) | 創建一個PreparedStatement對象,用於將參數化的SQL語句發送到數據庫 |
void setAutoCommit(boolean autoCommit) | 將此連接的自動提交模式設置爲給定狀態。 |
void commit() | 使自上一次提交/回滾以來的所有更改永久生效,並釋放此Connection對象當前持有的所有數據庫鎖。 |
void rollback() | 撤消在當前事務中進行的所有更改,並釋放此Connection對象當前持有的所有數據庫鎖。 |
代碼應用片段:
Statement stmt = conn.createStatement();
int count = stmt.executeUpdate(sql);
3.3 Statement
用於執行靜態SQL語句並返回其產生的結果的對象。
方法 | 描述 |
---|---|
boolean execute(String sql) | 執行任意給定的SQL語句,該語句可能返回多個結果。 |
int executeUpdate(String sql) | 執行DML(insert、update、delete)返回改變行數,或者執行DDL(create、alter、drop)不返回任何內容。 |
ResultSet executeQuery(String sql) | 執行給定的SQL語句,該語句返回一個 ResultSet對象。 |
代碼應用片段:
Statement stmt = null;
int count = stmt.executeUpdate(sql);
int count = stmt.executeUpdate(sql);
ResultSet rs = stmt.executeQuery(sql);
3.4 PreparedStatement
表示預編譯的 SQL 語句的對象,SQL 語句已預編譯並存儲在 PreparedStatement 對象中。然後可以使用該對象多次有效地執行該語句。預編譯 SQL 時,參數用佔位符(?)佔位,等應用時再用實際參數替換佔位符(?)。
方法 | 描述 |
---|---|
PreparedStatement Connection.prepareStatement(String sql) | 創建一個 PreparedStatement對象,用於將參數化的SQL語句發送到數據庫。 |
setXXX(參數1,參數2) | 給預編譯SQL語句中的佔位符 ? 賦值 |
注意:
- Xxx 可以爲任意基本類型,與數據庫中一致。
- 參數1:佔位符(?)的位置,從1開始計數
- 參數2:佔位符(?)的替換值
代碼應用片段:
//定義預編譯 SQL 語句,具體參數用佔位符(?)代替
String sql1 = "update account set a_money = a_money - ? where id = ?";
String sql2 = "update account set a_money = a_money + ? where id = ?";
//預編譯sql對象
PreparedStatement pstmt1 = conn.prepareStatement(sql1);
PreparedStatement pstmt2 = conn.prepareStatement(sql2);
//設置參數
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);
3.5 ResultSet
代表數據庫結果集的數據表,通常通過執行查詢數據庫的語句來生成。
方法 | 描述 |
---|---|
boolean next() | 向後移動遊標,判斷當前行是否有記錄,有則返回 true,反之返回false |
getXxx() | 獲取Xxx類型的數據 |
關於getXxx()方法的注意事項:
- Xxx爲基本數據類型,如:getString()、getInt()等。
- 參數可以是列的編號或者是列的名稱。
代碼應用片段
while(resultset.next()){
int id = resultset.getInt(1);
String name = resultset.getString("a_name");
double money = resultset.getDouble(3);
System.out.println(id + "---" + name + "---" + money);
}
4. 抽取 JDBC 的工具類
4.1 目的
簡化代碼編寫,增加代碼的可維護性,將 JDBC 的基本操作放到一個工具類中,用配置文件來獲取連接信息,降低耦合。
4.2 操作
在一個類中完成註冊驅動、獲取連接、釋放資源等 JDBC 相關操作,抽取一個方法獲取連接對象,用配置文件(jdbc.properties)的方式保存連接信息,讓工具類具有通用性。
4.3 配置文件的編寫
url=jdbc:mysql:///demo_test?serverTimezone=UTC
user=root
password=root
driver=com.mysql.cj.jdbc.Driver
4.4 工具類的編寫
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
/**
* JDBC工具類
*/
public class JdbcUtils {
//聲明成員變量,只有靜態變量才能被靜態方法訪問。
private static String url;
private static String user;
private static String password;
private static String driver;
/**
* 文件的讀取,只需要讀取一次即可拿到這些值,使用靜態代碼塊
*/
static {
//讀取資源文件,獲取值。
try {
//1. 創建Properties集合類
Properties pro = new Properties();
//獲取src路徑下的文件的方法————》類加載器 ClassLoader
ClassLoader classLoader = JdbcUtils.class.getClassLoader();
URL res = classLoader.getResource("jdbc.properties");
String path = res.getPath();
System.out.println(path);
//2. 加載文件
pro.load(new FileReader(path));
//3. 獲取數據,賦值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//4. 註冊驅動
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 獲取連接的對象
* @return 連接對象
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user, password);
}
/**
* 釋放資源
* @param stmt
* @param conn
*/
public static void close(Statement stmt, Connection conn){
if (stmt != null){
try {
stmt.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
/**
* 釋放資源重載
* @param rs
* @param stmt
* @param conn
*/
public static void close(ResultSet rs, Statement stmt, Connection conn){
if (rs != null){
try {
rs.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (stmt != null){
try {
stmt.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
5. 綜合實例
案例需求:完成張三和李四的轉賬操作,張三賬戶 -500 ,李四賬戶 +500
- 創建數據庫
-- 創建用戶賬單表
create table account(
id INT PRIMARY KEY AUTO_INCREMENT,
a_name varchar(30),
a_money double
);
-- 添加張三、李四的賬戶
insert into account(id,a_name,a_money) values
(1,"張三",1000),
(2,"李四",1000);
-- 查詢表
select * from account;
-
編寫 jdbc.properties 配置文件,放在src目錄下。內如參照 JDBC工具類抽取。
-
編寫工具類,內容參照 JDBC 工具類抽取。
-
編寫主類
package base.jdbc;
import base.util.JdbcUtils;
import java.sql.*;
/**
* 轉賬操作
*/
public class JdbcDemo8 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
try {
//1.獲取連接
conn = JdbcUtils.getConnection();
//開啓事務管理
conn.setAutoCommit(false);//值爲false開啓
//2.定義sql
//2.1 張三 - 500
String sql1 = "update account set a_money = a_money - ? where id = ?";
//2.2 李四 + 500
String sql2 = "update account set a_money = a_money + ? where id = ?";
//3. 獲取執行sql對象,預編譯,參數用 ? 佔位符
pstmt1 = conn.prepareStatement(sql1);
pstmt2 = conn.prepareStatement(sql2);
//4.設置參數佔位符的參數
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);
//5.執行sql
pstmt1.executeUpdate();
pstmt2.executeUpdate();
//提交改變
conn.commit();
} catch (Exception e) {
try{
if (conn != null) {
conn.rollback();
}
} catch (SQLException se){
se.printStackTrace();
}
e.printStackTrace();
} finally {
JdbcUtils.close(pstmt1,conn);
JdbcUtils.close(pstmt2,null);
}
}
}
- 再次查詢表中內容
select * from account;
時間:2019年10月29日19:17:36