用Java編程語言和JDBC開發的程序是可以跨平臺運行的,并且是不受供應商限制的.
4.1 JDBC的設計
JDBC由兩層組成,上面一層是JDBC API,負責與JDBC管理器驅動程序API進行通信,將各個不同的SQL語句發送給它;該管理器(對程序員是透明的)再與實際連接到數據庫的各個第三方驅動程序進行通信,并且返回查詢的信息,或者執行由查詢規定的操作.
JDBC驅動程序分為以下幾種類型:
類型1驅動程序
負責將JDBC轉換為ODBC,并且使用一個ODBC驅動程序與數據庫進行通信
類型2驅動程序
部分使用Java編程語言編寫的和部分使用本機代碼編寫的驅動程序,用于與數據庫的客戶機API進行通信
類型3驅動程序
純粹的Java客戶程序庫,它使用跨數據庫協議,將數據庫訪問請求傳輸給服務器組件,然后該服務器組件將訪問請求轉換成特定的數據庫協議
類型4驅動程序
純粹的Java庫,用于JDBC訪問請求直接轉換成特定數據庫協議
4.2 結構化查詢語言
JDBC是個到SQL(結構化查詢語言)的接口,而SQL實際上是與所有最新型的關系數據庫之間的接口.
4.3 安裝JDBC
建議最好不要使用Java2 SDK配備的JDBC/ODBC橋接器驅動程序,更加反對將該驅動程序用于Access這樣的桌面數據庫.
4.4 JDBC編程的基本概念
1. 數據庫URL
語法: jdbc:subprotocol name:other stuff
其中subprotocol特定驅動程序, other stuff參數的格式要根據它使用的子協議而定.
2. 建立連接
Class.forName(驅動程序類); 注冊驅動程序
String url = …;
String username = …;
String password = …;
Connetion conn = DriverManager.getConnection(url, username, password);
讀取屬性文件建立連接
Properties props = new Properties();
FileInputStream in = new FileInputStream(“database.properties”);
props.load(in);
in.close();
String drivers = props.getProperty(“jdbc.drivers”);
String url = props.getProperty(“jdbc.drivers”);
String username = props.getProperty(“jdbc.username”);
String password = props.getProperty(“jdbc.password”);
Connetion conn = DriverManager.getConnection(url, username, password);
3. 執行SQL命令
Statement stat = conn.createStatement();
String sql = …;
ResultSet rs = stat.executeQuery(sql);/stat.executeUpdate(sql);
while(rs.next()){
…
}
4. 高級SQL類型
Blob b=resultSet.getBlob(1);
InputStream bin=b.getBinaryStryeam();
Clob c=resultSet.getClob(2);
Reader cReader=c.getCharacterStream();
寫入:
FileInputStream fis=new
FileInputStream(f,Connection conn);
byte[] buffer=new byte[1024];
data=null;
int sept=0;int len=0;
while((sept=fis.read(buffer))!=-1){
if(data==null){
len=sept;
data=buffer;
}else{
byte[] temp;
int tempLength;
tempLength=len+sept;
temp=new byte[tempLength];
data=temp;
len=tempLength;
}
if(len!=data.length()){
byte temp=new byte[len];
data=temp;
}
}
String sql="insert into fileData (filename,blobData) value(?,?)";
PreparedStatement ps=conn.prepareStatement(sql);
ps.setString(1,f.getName());
ps.setObject(2,data);
ps.executeUpdate();
讀出:
try {
Clob c=resultSet.getClob(2);
Reader reader=c.getCharacterStream():
if (reader == null) {
return null;
}
StringBuffer sb = new StringBuffer();
char[] charbuf = new char[4096];
for (int i = reader.read(charbuf); i >
0; i = reader.read(charbuf)) {
sb.append(charbuf, 0, i);
}
return sb.toString();
} catch (Exception e) {
return "";
}
4.5 執行查詢操作
采用宿主變量方式:
String userId = 1;
String sql = “select * form user where user_id=?”;
PreparedStatement pStat = conn.prepareStatement(sql);
pStat.setString(1,userId);
ResultSet rs = pStat.executeQuery();
4.6 可滾動的和可更新的結果集
1. 可滾動的結果集
Statement stat = conn.createStatement(type,concurrency);
或
PreparedStatement stat = conn.prepareStatement(command,type, concurrency);
其中
Type包括:
ResultSet.TYPE_FORWARD_ONLY 不能滾動
ResultSet.TYPE_SCROLL_INSENSITIVE 可以滾動,但變化不敏感
ResultSet.TYPE_SCROLL_SENSITIVE 可以滾動,但變化敏感
Concurrency包括:
ResultSet.CONCUR_READ_ONLY 不能更新
ResultSet.CONCUR_UPDATABLE 可以更新
常用方法:
rs.previous() 滾動結果集
rs.relative(n) 將光標向后或向前移動n行
rs.absolute(n) 將光標設置到某個特定的行號上
rs.getRow() 獲得當前的行號
2. 可更新的結果集
常用方法:
rs.getConcurrency() 查看結果集是否可更新
rs.updateXxx() 只能用于修改行的值,不能修改數據庫
rs.updateRow() 將當前行中所有信息更新發送給數據庫
rs.cancelRowUpdates() 撤銷對當前行的更新
rs.moveToInsertRow() 將光標移到一個特定的位置
rs.insertRow() 將該新行傳遞給數據庫
rs.moveToCurrentRow() 將光標移回之前位置
rs.deleteRow() 刪除光標下的行
例子:
rs. moveToInsertRow();
rs.updateString(“Title”,title);
rs.updateString(“Isbn”,isbn);
rs.insertRow();
rs.moveToCurrentRow();
4.7 元數據
元數據是在SQL中用于描述數據庫或者它的各個部分之一的數據;分為關于數據庫的元數據和關于結構集合的元數據.
DatabaseMetaData conn.getMetaData() 用于提供關于數據庫的元數據
ResultSetMetaData rs.getMetaData() 用于提供關于結構集合的元數據
4.8 事務
如果將各個更新命令組合成一個事務,可以實現數據庫數據的完整性;在提交事務時,如果在它中間某個位置上運行失敗,它可以執行回退操作,并且該數據庫將自動撤銷提交事務以來進行的所有更新及所產生的影響.
在默認情況下,數據庫連接處于自動提交方式,并且每個SQL命令一旦被執行,便被提交給該數據庫.一旦命令被提交,就無法進行回退操作.
批量更新: 一序列命令將作為一個批量來集中和提交,命令不包括Select查詢.
String sql = …;
stat.addBatch(sql);
while(…){
sql = …
stat.addBatch(sql);
}
stat.executeBatch();
4.9 高級連接管理
在企業級環境中部署JDBC應用程序時,數據庫連接的管理納入了JNDI(Java命令與目錄接口)之中.一個目錄負責管理整個企業中的數據源的位置.使用目錄后,就可以對用戶名、口令、數據庫名字和JDBC URL實施集中管理.
Context jndi = …;
DataSource source = (DataSource)jndi.lookup(“jdbc/corejava”);
Connection conn = source.getConnection(username,password);