Sybase JDBC驱动的改进

** Sybase JDBC ** ** 驱动的改进 ** ** ( ** ** jConnect™ for JDBC ** ** ) ** ** **

兕丢疋没有魔法

** 适宜读者: ** ** **

正在使用 JSP 建立网站,或者开发 J2EE 应用程序;

使用 Sybase SQL Server 做为数据库服务器;

要求不能改变数据库使用的字符集设置;

使用或不使用 Hibernate 等 ORM 工具;

如果你的情况正如上述,那么建议你阅读本文。

** 方法概述: ** ** **

建立 JDBC 驱动程序的包装类,在包装类中加入改进的字符集和获取自动生成编号功能。

** 针对平台: ** ** **

Windows 2000/XP (主要是使用新版 cmd console 的新增 shell 语法)

jConnect™ 5.5

Sybase 公司于 2001 年推出的 JDBC 驱动程序 jConnect™ ,至今似乎就没有改动过。目前最高版本为 5.5 ,是按照 J2SE 1.2 规范设计的,而现在用得较多的是 J2SE 1.4 ,因此有很多特性都没有提供。特别是国际化问题, jConnect™ 的实现一直在困扰我,直到有一天拿 jConnect™ 和其它 JDBC 驱动作比较时才发现原来是 jConnect™ 的 BUG !

为了让读者不会被同样的问题困扰,我把具体的改进方法写出来,供大家参考:

首先需要对 jConnect™ 逆向工程(侵犯版权?管不了那么多了!),将 jconnect.jar 解开,用 jad 对其反编译:

C:\jconnect>for /d /r %i in () do jad -s .java -d %i %i\

有些 .class 文件可能无法正常解开,不过不要紧,因为我们只改动一个文件:

com/sybase/jdbc2/jdbc/SybDriver.java

除此之外,添加如下文件:

com/sybase/jdbc2/jdbc/CachedCharset.java

com/sybase/jdbc2/jdbc/_SybConnection.java

com/sybase/jdbc2/jdbc/_SybStatement.java

com/sybase/jdbc2/jdbc/_SybPreparedStatement.java

com/sybase/jdbc2/jdbc/_SybCallableStatement.java

com/sybase/jdbc2/jdbc/_SybResultSet.java

com/sybase/jdbc2/jdbc/P_Connection.java

com/sybase/jdbc2/jdbc/P_Statement.java

com/sybase/jdbc2/jdbc/P_PreparedStatement.java

com/sybase/jdbc2/jdbc/P_CallableStatement.java

com/sybase/jdbc2/jdbc/P_ResultSet.java

新增的文件用于实现新的特性,为了区别新旧两个 JDBC ,我们约定将连接 URL 改成如下格式:

jdbc:stupy( 新增属性 ):sybase:Tds:

 1<server>:  <port>/<database>
 2
 3以区别于: 
 4
 5jdbc:sybase:Tds:<server>:  <port>/<database>
 6
 7举例: 
 8
 9jdbc:stupy(charset=gb2312):sybase:Tds:127.0.0.1:  5000/BookStore 
10
11为了识别这个新的  URL  ,找到  SybDriver.java  中  acceptsURL  方法,加入: 
12
13** public  ** **boolean** acceptsURL(String url) 
14
15** throws  ** SQLException 
16
17{ 
18
19** _if_ ** _ (url.startsWith(  _ _ "jdbc:stupy:"  _ _ ))  _ _ _
20
21** _return_ ** _ acceptsURL(url.replaceFirst(  _ _ "stupy\\\\(.*?\\\\)?:"  _ _ ,  _ _ ""  _ _ ));  _ _ _
22
23** int  ** index = url.indexOf(  '/'  ); 
24
25** if  ** (index != -1) 
26
27…… 
28
29同理,在  SybDriver.java  中  connect(String url, Properties info)  中加入同样的内容(为什么不是其它  connect  方法?因为我们只需要关心  public  的方法),同时根据  URL  返回不同的  Connection  对象: 
30
31**public** **final** Connection connect(String url, Properties info) 
32
33**throws** SQLException 
34
35{ 
36
37String stupy_props = **null** ; 
38
39**if** (url.startsWith(  "jdbc:stupy"  )) { 
40
41stupy_props = url.substring(10, url.indexOf(  ":"  , 10)); 
42
43**if** (stupy_props.startsWith(  "("  )) 
44
45stupy_props = stupy_props.substring(1, stupy_props.length()-1); 
46
47url = url.replaceFirst(  "stupy\\\\(.*?\\\\)?:"  ,  ""  ); 
48
49} 
50
51Debug.println( **this** ,  "Connect("  \+ url +  ")"  ); 
52
53SybProperty props = **new** SybProperty(info, _version); 
54
55SybUrlManager uMgr = **new** SybUrlManager(url, info, props); 
56
57SybUrlProvider up = uMgr.getUrlProvider(); 
58
59**if** (up == **null** ) 
60
61**return** **null** ; 
62
63SybConnection conn = **new** SybConnection(up, url); 
64
65**if** (_msgHandler != **null** ) 
66
67conn.setSybMessageHandler(_msgHandler); 
68
69java.sql.SQLWarning w = props.getWarnings(); 
70
71**if** (w != **null** ) 
72
73conn.handleSQLE(w); 
74
75**if** (stupy_props != **null** ) 
76
77**return** **new** _SybConnection(conn, stupy_props); 
78
79**return** conn; 
80
81} 
82
83接下来,建立我们自己的特性实现。为了突出重点,我们需要建立一些辅助工具,包括  5  个中间包装类  P_xxx  ,  1  个简单的具有缓存功能的字符集类  CachedCharset  : 
84
85中间包装类的作用非常简单,它聚合一个外部对象,将所有方法调用转移到外部对象上。为什么不用继承呢?有几个原因,一是  Java  不支持多继承,二是为了重载已经声明为  final  的那些方法。这  5  个包装类因为本质上非常简单,比如包装类  P_ResultSet  ,它的构造指定一个将被聚合的目标  ResultSet  实例  rs  ,  P_ResultSet  的所有方法调用如  getString(String colname)  将返回  rs.getString(colname)  。为了方便读者使用  CP  技术  (Copy/Paste)  ,将这  5  个包装类贴在本文最后。</database></port></server></database></port></server>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus