用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);