JDBC (Java Database Connectivity) 是 Java 操作關係型資料庫的標準 API。本文提供連接 Oracle 與 SQL Server 的完整可運行代碼,涵蓋驅動載入、連接建立、PreparedStatement 參數化查詢、資源釋放等核心流程,並說明生產環境關鍵優化點。
Class.forName("driver.class.Name")DriverManager.getConnection(url, user, pwd)conn.prepareStatement(sql)stmt.setXxx(index, value)executeUpdate() / executeQuery()ResultSet.next() + getXxx()oracle.jdbc.driver.OracleDriver (ojdbc6/ojdbc8.jar)jdbc:oracle:thin:@host:port:SID 或 jdbc:oracle:thin:@//host:port/service_namepublic class JdbcOracleDemo {
// 靜態塊載入驅動(僅一次)
static {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
throw new ExceptionInInitializerError(e);
}
}
public static void main(String[] args) {
delete();
// insert();
select();
}
// 增/刪/改 通用模板
public static void executeUpdate(String sql, Object... params) {
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:ORCL", "username", "password");
stmt = conn.prepareStatement(sql);
bindParams(stmt, params);
int rows = stmt.executeUpdate();
System.out.println("影響行數:" + rows);
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeQuietly(stmt, conn);
}
}
// 查詢通用模板
public static void executeQuery(String sql, ResultSetHandler handler, Object... params) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:ORCL", "username", "password");
stmt = conn.prepareStatement(sql);
bindParams(stmt, params);
rs = stmt.executeQuery();
while (rs.next()) {
handler.handle(rs);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeQuietly(rs, stmt, conn);
}
}
// 具體業務方法
public static void insert() {
executeUpdate("INSERT INTO ProductType(Name, Up) VALUES(?, ?)", "新類型", 0);
}
public static void delete() {
executeUpdate("DELETE FROM ProductType WHERE Id=?", 21);
}
public static void select() {
executeQuery(
"SELECT id, name, up FROM ProductType WHERE Id > ? AND Name LIKE ?",
rs -> System.out.println(rs.getInt("id") + "\t" + rs.getString("name") + "\t" + rs.getInt("up")),
5, "%能%"
);
}
// 工具方法
private static void bindParams(PreparedStatement stmt, Object... params) throws SQLException {
for (int i = 0; i < params.length; i++) {
stmt.setObject(i + 1, params[i]);
}
}
private static void closeQuietly(AutoCloseable... resources) {
for (AutoCloseable r : resources) {
if (r != null) try { r.close(); } catch (Exception ignored) {}
}
}
@FunctionalInterface
interface ResultSetHandler {
void handle(ResultSet rs) throws SQLException;
}
}
com.microsoft.sqlserver.jdbc.SQLServerDriver (mssql-jdbc.jar)jdbc:sqlserver://host:port;databaseName=dbname[Order], [Name]// 連接
conn = DriverManager.getConnection(
"jdbc:sqlserver://localhost:1433;databaseName=GoMall", "sa", "sa");
// 插入(方括號轉義)
stmt = conn.prepareStatement("INSERT INTO [ProductType]([Name], [Up]) VALUES(?, ?)");
// 查詢
stmt = conn.prepareStatement(
"SELECT [Id], [Name], [Up] FROM [GoMall].[dbo].[ProductType] WHERE [Id] > ? AND [Name] LIKE ?");
| 問題 | 解決方案 |
|---|---|
| 頻繁創建/銷毀連接開銷大 | 使用連接池:HikariCP(推薦)、Druid、Tomcat JDBC Pool |
| 硬編碼連接資訊不安全 | 外部化配置:db.properties + Spring @Value / Environment |
| SQL 注入風險 | 全程使用 PreparedStatement 參數化,絕不拼接 SQL 字串 |
| 資源洩漏導致連接耗盡 | try-with-resources (Java 7+) 或 finally 確保關閉,連接池配置 maxLifetime、idleTimeout |
| 長事務阻塞連接池 | 業務邏輯與事務邊界分離,@Transactional 盡量精細 |
| 大量數據查詢 OOM | 使用 setFetchSize()、游標/流式讀取、分頁查詢 |
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:ORCL");
config.setUsername("user");
config.setPassword("pwd");
config.setMaximumPoolSize(20);
config.setMinimumIdle(5);
config.setConnectionTimeout(30000);
config.setIdleTimeout(600000);
config.setMaxLifetime(1800000);
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
DataSource ds = new HikariDataSource(config);
掌握 JDBC 基礎並引入成熟連接池,是構建高效穩定 Java 數據訪問層的關鍵。