当前的java版本提供了完备的工具,可将输出内容从关系数据库查询转换成xml。最终获得的将是一个dom(文档对象模型)文档对象。利用xsl(可扩展样式语言),它进而能转换成任意输出格式。本文介绍如何构建一个接口,用它读取与jdbc兼容的任何关系数据库,创建一个结果集,以便转换成任何类型的字符输出。
接口
最开始必须定义一个接口。这个接口在实现后,应该能建立一个数据库连接、向其传递一个sql查询、读取结果以及创建一个dom文档对象。下面的databasehandler接口定义了与数据库进行交互的行为(注意,本例缺少import语句,所以不能编译)。尤其要注意的是,getdocument()查询所返回的文档将由其他进程转换成所需的输出类型,这种转换是独立于数据库的。
public interface databasehandler{
document getdocument(string sqlquery);
string geturlstring();
void seturlstring(string urlstring);
string getusername();
void setusername(string username);
string getpassword();
void setpassword(string password);
string getdrivername();
void setdrivername(string drivername);
}
这是与数据库交互所需的最起码的行为。它包括几个get和set方法,用于确保数据库驱动程序名称、用户名和密码都得到了设置,或者以后能够检索到。下面总结了databasehandler的需求:
urlstring
username
password
sqlquery string
drivername
调用set方法之后,getdocument()方法将完成所有实际的工作:
document getdocument(string sqlquery);
传给set方法的所有输入都可能已经传给getdocument()方法。从重用性的角度说,应该对这两个方法进行分隔,使类的实现能方便和灵活地利用这种多重输入传递功能。
接口的一个抽象实现
接着要定义一个抽象类,它负责实现要求的大多数行为和操作,但某种特定数据库类型需要的那些行为必须排除在外。abstractdatabasehandler执行set和get方法的泛化操作,而且一旦设置好所有数据库处理参数,abstractdatabasehandler就要执行与数据库进行交互的泛化操作。惟一需要拿掉的就是与特定数据库类型有关的那些细节,以及为了获得databasehandler的一个具体实现而必须定义的设置细节。
get和set方法负责设置私有类变量;通过扩展abstractdatabasehandler而创建数据库处理器对象时,这些私有类变量将发生变化。这个过程是非常直观易懂的,如清单a所示。
getdocument()方法中的操作位于一个try catch块中。数据库事务处理过程中一旦发生任何错误,或者要求的任何输入参数没有设置,错误就会被捕捉。sqlexception允许多个异常链接到一起,这为我们带来了极大的方便。你必须遍历sqlexception,检查数据库交互过程中可能发生的所有问题。
} catch (sqlexceptionsqle) {
while(sqle != null) {
system.err.println ("**** sqlexception ****/n");
system.err.println ("** sqlstate: " + sqle.getsqlstate() + "/n");
system.err.println ("** message: " + sqle.getmessage() + "/n");
system.err.println ("** error code: " + sqle.geterrorcode() + "/n");
system.err.println ("***********/n");
/* there could be multiple exception messages chained together. */
sqle= sqle.getnextexception();
和其他任何异常一样,你可以为异常处理实现一个java日志,用它记录发生的任何问题。必须确保可能发生的所有异常都包含在try catchā?????块中,以便分门别类地采取操作,让用户知道执行期间发生了什么问题。下面总结了sqlexception包含的信息:
描述错误一个字符串
一个sqlstate字符串 string
一个整型错误代码,它是不同的厂商特有的
到下一个异常的链接
getdocument()方法首先检查要求的所有参数是否齐备,否则引发一个异常:
if(geturlstring() == null){
throw new exception("database url string is not set.");
}
if(getusername() == null){
throw new exception("database user name is not set.");
}
if (getpassword() == null){
throw new exception("database password is not set.");
}
if (getdrivername() == null){
throw new exception("database driver name is not set.");
}
一个sql查询字符串作为输入来传递。它可为你需要的任何sql字符串,比如:
select * from mytable;
select overdue, name, duedate, description from myactiontable;
接着创建jdbc驱动程序的一个实例,它向drivermanager注册驱动程序:
class.forname(getdrivername());
drivermanager现在可使用注册的驱动程序来创建一个数据库连接,并接管所有数据库操作。
不同的数据库要使用不同的url连接字符串。对于oracle数据库,字符串的形式是:
host:port:sid
具体需要的值是在tsnames配置文件中定义的,该文件的名称是tnsnames.ora,其中的设置项如下所示:
mydb =
(description =
(address =
(protocol = tcp)
(host = serverx.www.mycompany.com)
(port = 1521)
)
(connect_data =
(sid = examplesid)
(global_name = exampledb)
)
)
然后根据前面设置的url字符串、用户名和密码来创建一个connection对象,再用connection对象来创建一个statement对象,并针对数据库执行查询,以便返回一个结果集对象。所有细节由jdbc无缝地处理。
取决于具体的sql语句,语句执行之后也许不会返回任何值。这个类验证是否缺少返回值,只有在至少返回了一个数据行的前提下,才在文档中添加element节点。列名要从一个resultsetmetadata对象中检索,该对象是通过结果集的一个get方法来获得的:
resultsetmetadatarsmd = resultset.getmetadata();
在一个while循环中,将使用结果集的游标或行号来遍历整个结果集,同时生成一个dom文档对象。
while(resultset.next()){
// add element and textnode objects which define each row and each data column.
}
处理了resultset及其元数据后,就结束了与数据库的交互。之后,就可用xml/dom对象来容纳数据,并用xsl来格式化数据。
小结
本文讲述了如何创建一个接口,以便为databasehandler定义泛化行为,以及如何用一个抽象类来实现它,以便将抽象类扩展成一个具体的、自定义的数据库处理程序。这种行为允许你透明地连接一个关系数据库,执行sql查询,并返回一个结果集,随后可以将它的数据转换成一个dom文档对象。
闽公网安备 35060202000074号