JDBC-數據庫連接,是由一些類和接口構成的API,是J2SE的一部分,有java.sql、javax.sql包組成。下面看一下JDBC API與應用程序和數據庫驅動及數據庫之間的關係:
可以看出JDBC是Sun公司爲應用程序與數據庫驅動之間提供的一組接口(規範)。數據庫驅動是實現數據庫操作的類,它並不由sun公司來實現,而是由具體的公司來根據sun提供的規範(JDBC)來製作
操作數據庫的步驟(以mySql爲例)
與ODBC類似,分爲以下幾步(2層JDBC體系結構爲例):
-
註冊驅動
-
建立連接
-
創建執行sql語句的對象
-
執行語句
-
處理執行結果
-
釋放資源
1 註冊驅動
常用的有3種方式:
直接註冊驅動:
DriverManager.registerDriver(com.mysql.jdbc.Driver);這種方式要求程序首先要引入驅動包,否則無法通過編譯。而且它可能會造成DriverManager中產生兩個一樣的驅動,並對具體的驅動類產生依賴,所以不推薦使用。
鍵值對方式:
System.setProperty(“jdbc.drivers”,”com.mysql.jdbc.Driver”);同時註冊多個驅動則用冒號隔開。這種方式如果事先不引入驅動包的情況下能通過編譯(因爲操作的都爲字符串,運行時肯定不行啦),所以雖然不會對具體的驅動類產生依賴,但註冊不太方便,所以很少使用。
Class.forName方式(類似反射):
Class.forName(“com.mysql.jdbc.Driver”); Class.forName函數的作用是根據類的名字將類裝載到虛擬機中(並未實例化);這種方式也不會對具體的驅動類產生依賴,而且使用很方便,所以推薦使用。
2. 建立連接
Connection conn=DriverManager.getConnection(url,uid,pwd);
url格式:JDBC:子協議:子名稱//主機名:端口/數據庫名?key=value&…
例如:jdbc:mysql://localhost:8086/jdbc;uid和pwd也可以用key=value的方式告訴數據庫。
其它參數:如,userUnicode=true&characterEncoding=gbk
3. 創建執行sql語句的對象
這裏有兩個對象可以使用:Statement
、PreparedStatement
對象
一般來說有參數的sql操作都用PreparedStatement對象,因爲它有防止sql注入等優點。兩者的區別這裏不多介紹,創建語句:(假設conn爲數據庫連接對象)
Statement st=conn.createStatement();
PreparedStatement ps=conn.prepareStatement(strSql);
可以看出在創建PreparedStatement
對象時即需要指明要執行的sql語句,因爲它會對sql語句進行預處理,例如進行一些防止sql注入的字符過濾等;而Statement
則在執行sql動作時才指明sql語句。
4. 執行語句(CURD)
查詢:st.executeQuery(strSql);或者ps. executeQuery();
非查詢(增、刪、改):st.executeUpdate(strSql);或ps.executeUpdate();
5. 處理執行結果
查詢:返回值用ResultSet接收,例:ResultSet rs=st.executeQuery(strsql)
非查詢(增、刪、改):返回值爲int
6. 釋放資源
依次釋放ResultSet、Statement(或PreparedStatement)、Connection對象,釋放順序與創建順序相反(類似“棧”結構)。
注意,Connection是非常稀有的資源,用完必須馬上釋放,它的使用原則是儘量晚的創建,儘量早的釋放,以減少佔用資源的時間。
下面看一個最普通的操作代碼:
//以mysql爲例
public static void test() throws ClassNotFoundException, SQLException{
/*1.註冊驅動(3種方法),依賴於驅動jar包的存在,否則無法通過編譯
DriverManager.registerDriver(new com.mysql.jdbc.Driver());*/
//方法2:System.setProperties("jdbc.drivers","com.mysql.jdbc.Driver");
//方法3:*****推薦使用******
Class.forName("com.mysql.jdbc.Driver");
//2.建立連接
Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:8086/jdbc","zhipeng","123456");
//3.創建語句執行對象
java.sql.Statement st=conn.createStatement();//使用Statement對象
//4.執行語句
ResultSet rs=st.executeQuery("select * from T_User");
//5.處理結果
while(rs.next()){
System.out.print(rs.getObject(1)+"\t"+rs.getObject(2)+"\t"+rs.getObject(3)+"\t");
}
//6.釋放資源,資源rs、st、conn的釋放順序與創建順序相反
rs.close();
st.close();
conn.close();
}
}
當然真正使用時要對上面的代碼進行優化封裝等,比如需要將註冊驅動、建立連接、釋放資源的操作封裝到一個工具類中,然後用單例模式爲該類加鎖(synchronized)以限制多線程衝突問題。
擴展
JDBC 訪問DB的體系結構分爲兩類(Driver是實現數據庫操作的類):
1) 2層:客戶-數據庫
2) 3層:客戶-中間層(WebLogicServer)-數據庫
上面6步操作使用JDBC直接訪問數據庫的方式一看就知道是2層的體系結構。下面簡單介紹3層的JDBC體系結構:
使用3層的JDBC體系結構訪問數據,首先要安裝WebLogicServer,然後在它上面配置一個連接池(Connection Pool)和一個數據源(Data Source)。
連接池作用:
1) 消除頻繁建立連接所需的負載
2) 是用於管理數據庫連接的管理對象
3) 提供可共享,安全的連接
數據源作用:
1) 從連接池中提供連接的被管理的工廠對象
2) 綁定到JNDI(便於在不同的數據源操作即分佈式操作)並使用管理控制檯配置
這樣就可以從JNDI中獲取驅動,然後包裝爲DataSource對象,然後用DataSource對象來建立Connection對象了
package testJDBC;
import java.beans.Statement;
import java.sql.Connection;
import java.sql.ResultSet;
import javax.activation.DataSource;
import javax.naming.Context;
import javax.naming.InitialContext;
public class TestThree {
public void test(){
//實例化Context對象
Context ctx=new InitialContext();
//從JNDI中查找驅動,幷包裝爲DataSource對象
DataSource ds=(DataSource)ctx.lookup("TestDataSource");
//用DataSource對象來創建Connection對象
Connection conn=ds.getConnection();
//其它的與2層體系的JDBC類似
java.sql.Statement st=conn.createStatement();
String sqlString="select * from T_User";
ResultSet res=st.executeQuery(sqlString);
while(res.next()){
System.out.println(res.getObject(1));
}
}
}