分享
 
 
 

如何写自己的Type3JDBC驱动

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

摘要:原文连接:http://www.Javaworld.com/javaworld/jw-05-2002/jw-0517-jdbcdriver.Html? 本文属于个人爱好翻译请尊重原作版权

如何写自己的type3 JDBC 驱动

第1部分:应用程序连接数据的简单方法

前言

你想不想写自己的JDBC驱动,或者是否想把现在的JDBC驱动转换成Type3的驱动呢?Type3 的驱动主要用于无需客户端设置的Internet/Intrant应用程序中,并且提供灵活的系统管理工具。本文中Nitin Nanda 和 Sunil Kumar描述了JDBC驱动的架构并概略讲解了Type3 JDBC驱动的三层结构。并演示了如何创建自己的Type3 JDBC驱动。

在Java中访问数据库系统你需要一个JDBC驱动。你可以自己写Type1到Type4的JDBC驱动,可以是纯Java的方式或者使用Java结合本地接口方法的复合方式。产品化的方式趋向于利用纯Java技术创建Type3或Type4的驱动程序。在Internet应用程序中访问数据库的效率和稳定性成为了关键因素,这时Type3 JDBC驱动显示出了它的优势。所以,要开发高效的、易部署的Internet应用,你通常需要将现在的Type1或Type2类型的JDBC替换成Type3类型的。

整个文章分为3个部分:

1. 应用程序连接数据库的简单方法。

2. 使用自定义的JDBC驱动编译、部署、访问数据。

3. 通过高级的日志功能、连接池、预处理数据集增强自定义的JWDriver的性能。

在这三个部分中,我们首先介绍了我们自己的Type3 JDBC驱动的结构和设计(第一部分),然后讲了如何实现和部署整个驱动(第二部分),最后讲解了如何在其中增加一些高级特性,比如SQL日志、连接池等(第三部分)。

注意:

在开始之前,也许你可以先看一下Nitin Nanda's的"JDBC Drivers in the Wild",这更有利于你理解JDBC驱动。

jdbc驱动的结构

JDBC为通用的数据库访问提供了一种程序级的接口。在一个特定的数据库环境下使用JDBC API你需要一个JDBC驱动来完成他们直接的协调运行。JDBC被分为四种类型或者说层次。每一个类型都有一个JDBC实现,以便满足日益增加的对平台独立性、执行效率和可管理性的要求。这四种类型分别是:

Type1:JDBC-ODBC(开方数据库连接)桥。

Type2:本地API,部分的Java驱动。

Type3:网络协议,完全的Java 驱动。

Type4:本地协议,完全的Java驱动。

所有的JDBC驱动都要实现下面四个JDBC类:Driver、Connection、Statement和ResultSet。包含在java.sql包种DriverManager类用于管理被加载的驱动。客户端应用程序通过它获得数据库连接。JDBC的Driver通过下面的方法加载:

Class.forName("com.jw.client.JWDriver");

当这个Driver被加载时它的staic部分的代码就会执行,通过DriverManager注册这个驱动。现在,只要客户端应用程序通过DriverManger.getConnection()方法,DriverManager就会转而调用Driver.connect()方法。每一个JDBC驱动必须实现java.sql.Driver接口。所以,JDBC驱动的Driver.connect方法会首先检测当前的驱动Url是否正确,然后会通过connet()方法返回一个Connection对象。

简单type3驱动的结构

为了向你展示Type3驱动的内容结构,我创建了一个自己的Type3JDBC驱动。如图1所示,我们的Type3驱动是基于网络协议、完全Java实现的,它分为3个层次,同时向你展示了JDBC是如何通过中间层的网络协议进行通信的。中间层服务讲请求传输(直接或间接的)给特定的数据库本地连接接口,然后通过这个接口将请求传输到数据库服务器。中间层用Java实现,数据库访问的实现通过JDBC-ODBC桥。

图1 JDBC Type3 的结构

对于applet,客户层驱动文件位于中间层服务器,并且可以直接下载。在JDBC驱动种RMI提供网络协议服务,负责驱动的客户端和服务端的通信。JDBC-ODBC桥使得JDBC请求可以传输到数据库服务器。

驱动的客户层为客户端程序提供了标准的JDBC接口,包括实现了java.sql.Driver接口的Driver类。同时还包含了JDBC的Connection、Statement、Result接口的实现。

客户端应用程序,比如applet,可以使用Type3驱动的客户层类进行开发,因为它实现了标准的JDBC接口拥有标准的JDBC功能。客户层类的Driver在内部会维护与中间层提供的远程接口之间的通信。这些远程接口提供了客户端传输JDBC请求要用到的基本方法。应用程序会调用已经实现了的Driver中的JDBC方法,随后这些调用会通过RMI发送到中间层。所有Driver类的客户层通过中间层来管理内部的RMI通信。

驱动的服务层是一个RMI服务器,它通过JDBC-ODBC桥来和数据库进行通信。驱动的服务层包含4个远程接口以及它们的实现,这些远程接口分别为JDBC的Driver、Connection、Statement和Result提供了访问接口。实现这些远程接口的类会在内部维护JDBC-ODBC的桥驱动的Connection、Statement和Result对象。

当客户层类调用远程接口的时候,远程接口的实现使用内部的JDBC对象与数据库通讯。

现在你已经了解了Type3 JDBC驱动的接口,下面让我们进一步的深入到客户层和服务器层中。

JDBC类驱动图

为了实现Type3 JDBC驱动,我们必须创建客户层和中间层。客户层类位于com.jw.client包中,中间层位于com.jw.server包中,让我们先来看看客户层。

客户层类

客户层包com.jw.client中包含下面几个类:

com.jw.client.JWDriver类:JDBC驱动(Driver)的实现类。

com.jw.client.JWConnection类:JDBC连接(Connection)的实现类。

com.jw.client.JWStatement类:JDBC表达式(Statement)的实现类。

com.jw.client.JWRseultSet类:JDBC结果集(ResultSet)的实现。

如图2所示,它描述了客户层和中间层Driver和Connection类之间的关系。

图2:Driver和Connection类图

让我们仔细的看看JWDriver类的内部:

JWDriver类

com.jw.client.JWDriver类实现了java.sql.Driver接口,它提供了通过DriverManager类注册自己并创建数据库连接的方法。这个类实现了远程Driver的封装以便提供JDBC驱动接口。在应用程序中通过下面的方法调用可以加载JWDriver:

Class.forName("com.jw.client.JWDriver");

当它通过DriverManager类加载后,上面的代码中forName方法会调用JWDriver类的static部分的代码。下面显示的代码中的static部分:

static

{

try

{

// Register the JWDriver with DriverManager

JWDriver driverInst = new JWDriver();

DriverManager.registerDriver(driverInst);

System.setSecurityManager(new RMISecurityManager());

}

...

}

JWDriver类同时还维护一个远程驱动的引用,com.jw.server.IremoteDriver,它位于中间层服务器。远程驱动的引用为JWDriver创建了数据库的连接。所以当应用程序需要获得一个数据库连接的时候就调用DriverManager.getConnection()方法,这时DriverManager的JWDriver.connect()方法会通过远程驱动的引用获得一个数据库连接。

简而言之,JWDriver.connect()方法完成如下超作:

 比较客户端程序传递的URL如果是一个不匹配的URL就返回一个null。

 如果不存在远程驱动引用就通过Naming.lookup()方法创建一个。JWDriver.connet()方法控制远程驱动来创建数据库连接。:

if(remoteDriver == null)

{

remoteDriver= RemoteDriver)Naming.lookup

("rmi://"+serverName

+":1099"+"/RemoteDriver");

}

 创建、使用如上方法创建的数据库连接,并将创建的数据库连接返回给调用它的应用程序。RemoteDriver.getConnetion()方法是中间层JDBC驱动的远程调用,从中间层获得的远程Connection作为一个应用保存在JWConnection类对象中。JWConnection类可以通过下面的方法获得:

{

IRemoteConnection remoteConInstance =

(IRemoteConnection)remoteDriver.getConnection();

localConInstance = new JWConnection

(remoteConInstance);

.

..

return (Connection)localConInstance;

}

下面我们一起来仔细的看看jwconnection类。

JWConnection类

Com.jw.client.JWConnection类实现了Connection接口,而且它还包含一个远程服务器IremoteConnection接口的引用。

客户端程序中的JWDriver.connect方法可以得到JWConnection对象的引用并创建一个JWConnection对象。这样客户端就可以通过JWConnection对象任意的调用JDBC Connection接口的方法了。JWConnection在内部调用远程服务器的Connection。比如当客户端调用conn.createStatement()方法时(conn是一个JWConnection的引用),其内部会调用一个RemoteConnection.createConnection()方法,并返回一个远程的Statement引用;JWConnectoin的createStatement方法会创建一个JWStatement对象;最后一个JWStatement对象会返回个客户端,这个对象中包含的Statement的引用:

public Statement createStatement() throws

SQLException

{

try

{

IRemoteStatement remStmt =

(IRemoteStatement) remoteConnection.createStatement();

JWStatement localStmtInstance = new JWStatement(remStmt);

return (Statement)localStmtInstance;

}

}

图3描述了客户层和中间层中Connection和Statemennt类之间的关系。

图 Connection和Statement之间的关系

下面再让我们来看看jwstatement类

JWStatement类

com.jw.clent.JWStatement类实现了JDBC Statement接口,同时引用了远程服务器的Statement接口。这个类封装了远程Statement存根,它提供了JDBC Statement接口,JWConnection.createStatemnt()方法创建了JWStatement对象并返回给客户端。这样客户端就可以使用JDBC Statement接口提供的所有方法,在内部JWStatement调用了远程的Statement。比如客户端调用stmt.executeQuery()方法,这个方法内部会调用RemoteStatement.executeQuery()方法并返回一个ResulstSet引用。最终,JWResultSet对象会返回到客户端,这个对象包含了ResultSet的引用:

public ResultSet executeQuery(String sqlQuery)

throws SQLException

{

try

{

IRemoteResultSet remoteRsInstance =

(IRemoteResultSet) remoteStmt.executeQuery(sqlQuery);

JWResultSet localRsInstance = new JWResultSet(remoteRsInstance);

return (ResultSet)localRsInstance;

}

catch(RemoteException ex)

{

throw(new SQLException(ex.getMessage()));

}

}

图4描述了客户层和中间层中Statement和ResultSet类之间的关系。

图4 Statement和ResultSet类之间的关系

下面我们来看看jwresultset类。

JWResultSet类

com.jw.clent. JWResultSet类实现了JDBC ResultSet接口,同时引用了远程服务器的ResultSet接口。这个类封装了远程ResultSet存根,它提供了JDBC ResultSet接口。JWStatement.executeQuery()方法创建想客户端返回一个JWResult对象,它包含了Result接口的引用。因此客户端程序可以使用JDBC Result提供的任何方法,JWResult对象内部会调用远程服务器的ResultSet。比如当客户端调用rs.next(rs一个一个JWResultSet对象的引用),next()方法内部会调用RemoteResultSet.getNextRow(),这个方法会返回一个包含行数据的数组。当客户端调用rs.getString(1)方法时会返回保存在JWResultSet中行数据的当前值。

public class JWResultSet implements

java.sql.ResultSet

{

// The current ResultSet data row

private Object[] row;//自己替换[]

...

public boolean next() throws SQLException

{

try

{

// Get the current data row from remote

ResultSet

// All the getXXX methods will get data from

local 'row'

row = remoteResultSet.getNextRow();

}

catch(Exception ex)

{

return false;

}

if(row == null)

{

return false;

}

return true;

}

}

中间层类

中间层类位于com.jw.server包中,包括下面几个类:

 com.jw.server.RemoteDriverImpl类:这是一个驱动类它负责获得数据库连接,同时作为RMI服务器。

 com.jw.server.RemoteConnectionImpl类:是一个Connection 类,并且它负责获得JDBC Statement。

 com.jw.server.RemoteStatementImpl类:是一个Statement类,并且它负责获得JDBC ResultSet。

 com.jw.server.RemoteResultSetImpl类:是一个ResultSet类。

下面我们详细分析每个类:

RemoteDriverImpl

RemoteDriverImpl扮演一个RMI服务器(它继承了UnicastRemoteObject)并向JDBC驱动客户端提供了getConnection()方法。图2显示了RemoteDriverImpl的其他类与接口之间的关系。

com.jw.server.IremoteDriver是一个扩展了Remote的接口,它提供了getConnection()方法。这个方法创建JDBC Connection并作为一个IremoteConnection的引用返回给客户端。

由于RemoteDriverImpl同时还是JDBC驱动服务器的RMI服务器,它会读取ODBC的数据源名称(DSN),从部署在服务层中的DriverSettings.properties

文件读取用户名和密码。

这些值可以创建一个JDBC Connection,此外,RemoteDriverImpl可以通过名称服务“RemoteDriver”注册自身,所有JDBC 的客户层可以通过Naming.lookup()方法与服务端连接。然后它会加载JDBC-ODBC桥来创建数据库连接:

public static void main(String args[])//自己替换[]

{

System.setSecurityManager(new RMISecurityManager());

try

{

// Get the data source name, data source user, data

source

// PassWord and log level

ResourceBundle settingsBundle =

ResourceBundle.getBundle(

"DriverSettings");

DSN = settingsBundle.getString("DSN");

dsUser = settingsBundle.getString("User");

dsPassword = settingsBundle.getString

("Password");

// Create a RemoteDriverImpl instance to register

with naming service

RemoteDriverImpl serverInstance = new

RemoteDriverImpl();

Naming.rebind

("RemoteDriver",serverInstance);

// Load the JDBC-ODBC Bridge driver

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

}

...

}

getConnection()方法创建了JDBC-ODBC连接,然后返回RemoteConnectionImpl对象远程接口的引用来控制JDBC-ODBC连接:

public IRemoteConnection getConnection()

throws RemoteException,SQLException

{

String URL="jdbc:odbc:"+DSN;

Connection sqlCon =

DriverManager.getConnection(URL,dsUser,dsPassword);

RemoteConnectionImpl ConnectionInstance =

new RemoteConnectionImpl(sqlCon);

return (IRemoteConnection)ConnectionInstance;

}

下面让我们来看看RemoteConnectionImpl。

RemoteConnectionImpl类

RemoteConnectionImpl继承了UnicastRemoteObject类并实现了IremoteConnection接口(图2、3显示了RemoteConnectionImpl类的其他类和接口的关系)。IremoteConnection接口提供了创建JDBC Statement和关闭数据库连接的方法,RemoteConnectionImpl同时封装了传入构造中的JDBC连接。

createStatement()创建了JDBC-ODBC Statement并返回RemoteConnectionImpl对象的引用来控制JDBC-ODBC Statement:

public IRemoteStatement createStatement() throws

RemoteException,SQLException

{

RemoteStatementImpl StmtImplInstance = new

RemoteStatementImpl(sqlConnection.createStatement());

return (IRemoteStatement)StmtImplInstance;

}

接下来closeConnection()方法通过内部封装的close()方法关闭JDBC Connection:

public void closeConnection() throws

RemoteException,SQLException

{

sqlConnection.close();

}

下面再看RemoteStatementImpl。

RemoteStatementImpl类

如图3、4中显示的RemoteStatementImpl类,它继承了UnicastRemoteObject类并实现了IremoteStatement接口。这个接口提供了创建JDBC ResultSet和关闭Statement对象的方法。RemoteStatementImpl同样封装了闯入构造的Statement对象。

executeQuery()方法创建了JDBC-ODBC的ResultSet并返回一个RemoteStatementImpl对象的引用来控制JDBC-ODBC的ResultSet:

public IRemoteResultSet executeQuery(String Query)

throws RemoteException,SQLException

{

ResultSet rs = sqlStatment.executeQuery(Query);

RemoteResultSetImpl remoteRs = new

RemoteResultSetImpl(rs);

return (IRemoteResultSet)remoteRs;

}

close()方法简单的关闭了JDBC Statement对象:

public void close() throws RemoteException,

SQLException

{

sqlStatment.close();

}

最后再来看看RemoteResultSetImpl类。

RemoteResultSetImpl类

RemoteResultSetImpl继承了UnicastRemoteObject类并实现了IremoteResult接口(图4 显示了RemoteResultSetImpl类的其他类和接口的关系)。IremoteResult接口获得JDBC ResultSet行数据并关闭ResultSet对象。RemoteResultSetImpl同样封装了构造中的ResultSet对象。

getNextRow()方法返回一个包含对象数组的JDBC ResultSet给客户端JWResultSet,如果ResultSet不包含任何数据会返回null:

public Object[] getNextRow() throws

RemoteException,SQLException//自己替换[]

{

// Return null if all data has already been

iterated

if(sqlRs.next() == false)

return null;

// Prepare the data row in an array of Objects

Object []row = new Object[colNum];//自己替换[]

for(int i = 1; i <= colNum; i++)

{

row[i-1] = sqlRs.getString(i);//自己替换[]

}

return row;

}

close()方法会关闭ResultSet对象:

public void close() throws

RemoteException,SQLException

{

sqlRs.close();

}

以上就是中间层中的所有类。

type3 总结

在这篇文章中,我向你展示了Type3 JDBC驱动的结构。驱动创建了客户层和服务层组件,并使用RMI实现它们之间的通信。我们还演示了客户层的不同对象如何通过引用与服务层中的远程对象交互。

在第2部分我会向你展示如何使用和部署这里创建的Type3驱动。我们将提供一个简单的应用程序,并通过序列图的方式向你展示驱动是如何加载的,如何创建一个JDBC Connection,如何创建一个 JDBC Statement。 (出处:http://www.knowsky.com)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有