Java 作為一種廣泛應用的編程語言,在企業(yè)級應用開發(fā)中扮演著重要角色。而數據庫作為數據存儲和管理的核心,與 Java 應用的交互至關重要。小編將詳細介紹 Java 如何連接數據庫、查詢數據,以及如何調用 MySQL 存儲過程,幫助開發(fā)者構建高效、可靠的數據庫應用。
一、Java 連接數據庫:JDBC 的力量
Java 通過 JDBC (Java Database Connectivity) API 來連接和操作各種數據庫。JDBC 提供了一組接口和類,允許 Java 程序與數據庫進行通信,執(zhí)行 SQL 語句,并處理結果集。
1. JDBC 連接數據庫的步驟:
加載數據庫驅動: 首先,需要加載對應數據庫的 JDBC 驅動程序。例如,連接 MySQL 數據庫,需要加載 MySQL Connector/J 驅動??梢允褂?Class.forName() 方法加載驅動。
try {
Class.forName("com.mysql.cj.jdbc.Driver"); // MySQL 8.0+
// Class.forName("com.mysql.jdbc.Driver"); // MySQL 5.x
} catch (ClassNotFoundException e) {
System.err.println("MySQL JDBC Driver not found!");
e.printStackTrace();
return; // 或拋出異常
}
建立數據庫連接: 使用 DriverManager.getConnection() 方法建立與數據庫的連接。需要提供數據庫 URL、用戶名和密碼。
String url = "jdbc:mysql://localhost:3306/mydatabase?serverTimezone=UTC"; // 數據庫 URL
String user = "myuser"; // 數據庫用戶名
String password = "mypassword"; // 數據庫密碼
Connection connection = null;
try {
connection = DriverManager.getConnection(url, user, password);
System.out.println("Connected to database!");
} catch (SQLException e) {
System.err.println("Failed to connect to database!");
e.printStackTrace();
return; // 或拋出異常
}
創(chuàng)建 Statement 或 PreparedStatement 對象: Statement 用于執(zhí)行靜態(tài) SQL 語句,而 PreparedStatement 用于執(zhí)行預編譯的 SQL 語句,可以防止 SQL 注入攻擊,并提高性能。
Statement statement = null;
PreparedStatement preparedStatement = null;
try {
statement = connection.createStatement();
String sql = "SELECT * FROM users";
ResultSet resultSet = statement.executeQuery(sql);
// 處理結果集
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String email = resultSet.getString("email");
System.out.println("ID: " + id + ", Name: " + name + ", Email: " + email);
}
// 使用 PreparedStatement
String sqlPrepared = "SELECT * FROM users WHERE id = ?";
preparedStatement = connection.prepareStatement(sqlPrepared);
preparedStatement.setInt(1, 1); // 設置參數
ResultSet resultSetPrepared = preparedStatement.executeQuery();
// 處理結果集
while (resultSetPrepared.next()) {
int id = resultSetPrepared.getInt("id");
String name = resultSetPrepared.getString("name");
String email = resultSetPrepared.getString("email");
System.out.println("ID: " + id + ", Name: " + name + ", Email: " + email);
}
} catch (SQLException e) {
System.err.println("Failed to execute SQL query!");
e.printStackTrace();
} finally {
// 關閉資源
try {
if (statement != null) statement.close();
if (preparedStatement != null) preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
執(zhí)行 SQL 語句: 使用 executeQuery() 方法執(zhí)行 SELECT 語句,返回 ResultSet 對象。使用 executeUpdate() 方法執(zhí)行 INSERT、UPDATE、DELETE 語句,返回受影響的行數。
處理結果集 (ResultSet): ResultSet 對象包含查詢結果。可以使用 next() 方法遍歷結果集,使用 getInt()、getString() 等方法獲取每一列的值。
關閉連接和資源: 在使用完數據庫連接后,務必關閉連接和相關的資源,如 Statement、PreparedStatement 和 ResultSet 對象,以釋放資源并避免連接泄漏。
finally {
try {
if (resultSet != null) resultSet.close();
if (statement != null) statement.close();
if (preparedStatement != null) preparedStatement.close();
if (connection != null) connection.close();
System.out.println("Connection closed.");
} catch (SQLException e) {
e.printStackTrace();
}
}
2. 數據庫連接池:提高性能
頻繁地建立和關閉數據庫連接會消耗大量資源。為了提高性能,可以使用數據庫連接池。連接池維護一組數據庫連接,當需要連接時,從連接池中獲取一個連接,使用完后歸還給連接池,避免了重復創(chuàng)建和銷毀連接的開銷。
常用的 Java 連接池有:
HikariCP: 高性能、輕量級的連接池。
Apache Commons DBCP: 穩(wěn)定、成熟的連接池。
C3P0: 功能豐富的連接池。
二、Java 調用 MySQL 存儲過程
存儲過程是在數據庫服務器上預先編譯好的 SQL 語句集合,可以接受參數,執(zhí)行復雜的業(yè)務邏輯,并返回結果。調用存儲過程可以提高性能,減少網絡傳輸,并增強安全性。
1. 創(chuàng)建 MySQL 存儲過程:
DELIMITER //
CREATE PROCEDURE GetUserById(IN userId INT, OUT userName VARCHAR(255), OUT userEmail VARCHAR(255))
BEGIN
SELECT name, email INTO userName, userEmail FROM users WHERE id = userId;
END //
DELIMITER ;
這個存儲過程 GetUserById 接受一個輸入參數 userId,并返回兩個輸出參數 userName 和 userEmail。
2. Java 調用存儲過程的步驟:
創(chuàng)建 CallableStatement 對象: 使用 Connection.prepareCall() 方法創(chuàng)建 CallableStatement 對象,指定存儲過程的名稱。
CallableStatement callableStatement = null;
try {
String sql = "{call GetUserById(?, ?, ?)}";
callableStatement = connection.prepareCall(sql);
} catch (SQLException e) {
System.err.println("Failed to create CallableStatement!");
e.printStackTrace();
return; // 或拋出異常
}
注冊輸出參數: 使用 registerOutParameter() 方法注冊存儲過程的輸出參數,指定參數的位置和數據類型。
try {
callableStatement.setInt(1, 1); // 設置輸入參數 userId
callableStatement.registerOutParameter(2, Types.VARCHAR); // 注冊輸出參數 userName
callableStatement.registerOutParameter(3, Types.VARCHAR); // 注冊輸出參數 userEmail
} catch (SQLException e) {
System.err.println("Failed to register output parameters!");
e.printStackTrace();
return; // 或拋出異常
}
執(zhí)行存儲過程: 使用 execute() 方法執(zhí)行存儲過程。
try {
callableStatement.execute();
} catch (SQLException e) {
System.err.println("Failed to execute stored procedure!");
e.printStackTrace();
return; // 或拋出異常
}
獲取輸出參數: 使用 getXXX() 方法獲取存儲過程的輸出參數,例如 getString() 獲取字符串類型的參數。
try {
String userName = callableStatement.getString(2); // 獲取 userName
String userEmail = callableStatement.getString(3); // 獲取 userEmail
System.out.println("User Name: " + userName + ", User Email: " + userEmail);
} catch (SQLException e) {
System.err.println("Failed to get output parameters!");
e.printStackTrace();
} finally {
// 關閉資源
try {
if (callableStatement != null) callableStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
3. 完整示例代碼:
import java.sql.*;
public class StoredProcedureExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydatabase?serverTimezone=UTC";
String user = "myuser";
String password = "mypassword";
Connection connection = null;
CallableStatement callableStatement = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connection = DriverManager.getConnection(url, user, password);
String sql = "{call GetUserById(?, ?, ?)}";
callableStatement = connection.prepareCall(sql);
callableStatement.setInt(1, 1); // 設置輸入參數 userId
callableStatement.registerOutParameter(2, Types.VARCHAR); // 注冊輸出參數 userName
callableStatement.registerOutParameter(3, Types.VARCHAR); // 注冊輸出參數 userEmail
callableStatement.execute();
String userName = callableStatement.getString(2); // 獲取 userName
String userEmail = callableStatement.getString(3); // 獲取 userEmail
System.out.println("User Name: " + userName + ", User Email: " + userEmail);
} catch (ClassNotFoundException e) {
System.err.println("MySQL JDBC Driver not found!");
e.printStackTrace();
} catch (SQLException e) {
System.err.println("Failed to connect or execute stored procedure!");
e.printStackTrace();
} finally {
try {
if (callableStatement != null) callableStatement.close();
if (connection != null) connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
小編詳細介紹了 Java 如何連接數據庫、查詢數據,以及如何調用 MySQL 存儲過程。掌握這些技術,可以幫助開發(fā)者構建高效、可靠的數據庫應用。在實際開發(fā)中,需要根據具體需求選擇合適的連接方式、查詢方式和存儲過程調用方式,并遵循最佳實踐,以提高應用的性能和安全性。