閱讀目錄
如今任何應用程序的開發幾乎都離不開數據庫,JDBC是為Java提供的一個平台無關的數據庫標准API,它提供了一個通用的SQL(Structured Query Language)數據庫存儲機制,該機制為多數關系型DBMS提供統一接口。現在業界有很多優秀的ORM(Object Relational Mapping)框架,例如全自動化的Hibernate和半自動化的MyBatis。這些框架是對JDBC的進一步封裝,在企業級應用開發中提高開發效率。
本系列文章主要講述Java數據庫編程基礎JDBC的相關知識,本文為系列開篇---Java數據庫編程之JDBC配置。
業界存在許多不同的數據庫,且它們所使用的協議也各不相同。為了使Java能夠與任何數據庫進行通信,Sun公司(已被Oracle收購)指定了兩套接口。應用程序開發者使用JDBC API,而數據庫供應商和工具開發商則使用JDBC驅動API。JDBC API為SQL訪問提供一套“純”Java API,JDBC驅動API允許第三方驅動程序可以連接到特定的數據庫。Sun公司還指定一套簡單的機制,以使得第三方驅動程序可以向驅動管理器注冊。這樣,數據庫供應商就可以提供自己的驅動程序,並插入到驅動管理器中。
這種接口組織方式遵循了微軟公司非常成功的ODBC模式(JDBC的命名體現了對ODBC的致敬),ODBC為C語言訪問數據庫提供了一套編程接口。JDBC和ODBC都基於同一個思想:根據API編寫的程序都可以與驅動管理器進行通信,而驅動管理器則通過驅動程序與實際數據庫進行通信。
JDBC到數據庫的通信路徑
編寫一個數據庫程序之前,需要收集大量的信息和文件,下面將討論這些內容。
在連接數據庫時,開發者必須使用各種與數據庫類型相關的參數,例如主機名、端口號和數據庫名。JDBC使用了一種與普通URL相類似的語法來描述數據源。數據庫URL語法:協議名 + IP地址(域名) + 端口號 + 數據庫名。下文以常用的兩種數據庫Oracle和MySql舉例。例如:
MySql:jdbc:mysql://localhost:3306/db_name
Oracle:jdbc:oracle:thin:@loaclhost:1521:orcl
開發數據庫程序時,需要獲得包含了所使用的數據庫的驅動程序程序的JAR文件,並導入到項目工程中。
Mysql:MySQL Connector/J
Oracle:Oracle Database 11g Release 2 JDBC Drivers
某些JDBC的JAR文件(例如包含在Java SE中的Derby驅動程序)將自動注冊驅動器類。如果驅動程序JAR不支持自動注冊,那就需要找出數據庫提供商使用的JDBC驅動器類的名字,常用的做法是使用Class類的靜態方法forName強制加載驅動器類。例如:
MySql:Class.forName("com.mysql.jdbc.Driver")
Oracle:Class.forName("oracle.jdbc.driver.OracleDriver")
在Java程序中,開發者可以在代碼中打開一個數據庫連接,例如:
1 2 3 4 5String url =
"jdbc:mysql//localhost:3306/db_name"
;
String user =
"root"
;
String password =
"root"
;
Connection conn = DriverManager.getConnection(url, user, password);
驅動管理器遍歷所有注冊過的驅動程序,以便找到一個能夠使用數據庫URL中指定的子協議的驅動程序。getConnection方法返回一個Connection對象,開發者使用Connection對象來執行SQL語句。
開發者一般將JDBC配置寫到配置文件中,便於管理修改,當然也可以寫在Java類裡。下面的程序清單(以Mysql為例)從名為jdbc.properties的文件中加載連接參數,並連接到數據庫。要想獲得數據庫連接,只需要調用DBConnection類的靜態方法getConnection
jdbc.properties配置文件
1 2 3 4driver=com.mysql.jdbc.Driver
url=jdbc:mysql:
//localhost:3306/test
user=root
password=root
DBConnection.java類
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66import
java.io.FileInputStream;
import
java.io.FileNotFoundException;
import
java.io.IOException;
import
java.sql.Connection;
import
java.sql.DriverManager;
import
java.sql.ResultSet;
import
java.sql.SQLException;
import
java.sql.Statement;
import
java.util.Properties;
public
class
DBConnection {
private
static
String config =
"src/jdbc.properties"
;
private
static
String driver;
private
static
String url;
private
static
String user;
private
static
String password;
/**
* 靜態代碼塊 注冊驅動器類
*/
static
{
Properties props =
new
Properties();
try
{
FileInputStream fis =
new
FileInputStream(config);
props.load(fis);
driver = props.getProperty(
"driver"
);
url = props.getProperty(
"url"
);
user = props.getProperty(
"user"
);
password = props.getProperty(
"password"
);
Class.forName(driver);
}
catch
(FileNotFoundException e) {
e.printStackTrace();
}
catch
(IOException e) {
e.printStackTrace();
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
}
public
static
Connection getConnection()
throws
SQLException {
return
DriverManager.getConnection(url, user, password);
}
public
static
void
close(Connection conn, Statement stmt, ResultSet rs) {
try
{
if
(rs !=
null
) {
rs.close();
}
if
(stmt !=
null
) {
stmt.close();
}
if
(conn !=
null
) {
conn.close();
}
}
catch
(SQLException e) {
e.printStackTrace();
}
}
public
static
void
close(Connection conn, Statement stmt) {
close(conn, stmt,
null
);
}
}
當使用完ResultSet、Statement或Connection對象時,應立即調用close方法。這些對象都使用了規模較大的數據結構,所以我們不應該等待垃圾回收器來處理它們。