一种同一数据库多个版本JDBC驱动共存方法和系统与流程

文档序号:16331342发布日期:2018-12-19 06:13阅读:1191来源:国知局
一种同一数据库多个版本JDBC驱动共存方法和系统与流程

本发明涉及数据访问技术领域,具体涉及一种同一数据库多个版本jdbc驱动共存方法和系统。

【背景技术】

java数据库连接(javadatabaseconnectivity,简写为jdbc)是java编程语言访问数据库的规范,它提供了一套完整的、独立于任何特定数据库的编程接口,使得java程序能够编写通用的数据库操作程序,而无需绑定到每种数据库不同的编程接口。

不同的数据库厂商发布数据库时会同时发布实现了jdbc接口的驱动程序,一般都是以jar包的形式提供。jdbc的工作原理可参考图1:java应用程序访问数据库时,一般需要将jar包放到java虚拟机(javavirtualmachine,简写为jvm)的classpath路径上,这样java应用程序启动后,java虚拟机可以自动通过classpath加载jar包中的驱动类,并将驱动类实例注册到jdbc驱动管理器(jdbcdrivermanager)中。java应用程序再通过驱动管理器获取到某个特定数据库的连接对象,并通过该连接对象调用jdbc接口(jdbcdriverinterface),进而执行对相应的数据库的各种操作。其中,连接对象和jdbc接口与数据库的实际交互则由数据库驱动实现。

在使用jdbc访问数据库时,主要包括以下步骤:加载驱动类、创建驱动类实例并向驱动管理器注册、通过驱动管理器创建连接对象、通过连接对象操作数据库以及关闭并释放连接对象。上述使用jdbc的方法对于一般的应用系统来说是没有问题的,因为对于一般的业务系统来说通常只需要访问一个数据库,但是在建设数据中心或者数据共享类应用时,很可能要访问企业不同时期建设的各种业务数据库来进行数据交换或者数据集成,此时上述方法和步骤无法支持在同一应用中同时访问同一种数据库的不同版本驱动,这是由于:

在传统方法中对于驱动类的加载为静态加载,静态加载jdbc驱动的方式无法加载多个类名相同的不同版本驱动,驱动管理器中也不支持同时注册多个类名相同但是实际实现不同的驱动,因此也就无法将同一种数据库中不同版本的jdbc驱动注册到dirvermanager中;如果直接这样做可能导致混乱,使得dirvermanager无法找到正确的驱动对象来创建连接。

鉴于此,克服上述现有技术所存在的缺陷是本技术领域亟待解决的问题。



技术实现要素:

本发明需要解决的技术问题是:

在使用jdbc访问数据库时,传统的静态加载方法无法同时加载一种数据库多个版本的jdbc驱动,驱动管理器中也不支持同时注册多个类名相同但是实际实现不同的驱动,使得java应用无法同时访问同一数据库的不同版本,进而影响不同版本间的数据交换和集成。

本发明通过如下技术方案达到上述目的:

第一方面,本发明提供了一种同一数据库多个版本jdbc驱动共存方法,包括:

通过urlclassloader动态加载驱动类;

通过动态加载的驱动类,动态创建驱动类实例;

使用driveradpter类封装原始的所述驱动类实例以得到driveradpter类实例,并将所述driveradpter类实例注册到驱动管理器;

通过所述驱动管理器中注册的driveradpter类实例创建数据库的连接对象;

从所述驱动管理器中注销当前的driveradpter类实例,以便进行下个版本驱动的动态加载;

其中,对于多个不同版本的jdbc驱动,分别使用不同的urlclassloader进行驱动类的加载,以便创建不同版本的驱动类实例。

优选的,在所述从所述驱动管理器中注销当前的driveradpter类实例之后,所述方法还包括:

通过各连接对象操作对应版本驱动下的数据库;

对于完成数据库操作的对应版本,关闭并释放对应的连接对象。

优选的,所述通过所述驱动管理器中注册的driveradpter类实例创建数据库的连接对象,具体为:所述驱动管理器调用已经注册的driveradpter类实例的acceptsurl(stringurl)方法;如果acceptsurl(stringurl)方法返回true且通过类加载器的检查,则利用对应的driveradpter类实例创建数据库的连接对象。

优选的,所述类加载器的检查具体为:所述驱动管理器检查appclassloader是否能够加载到由urlclassloader动态加载的驱动类,如果不能加载则报错;如果能加载则通过对类加载器的检查。

优选的,所述driveradpter类由appclassloader加载,使得所述driveradpter类位于java虚拟机的classpath路径上,进而通过类加载器的检查。

优选的,在执行所述通过所述驱动管理器中注册的driveradpter类实例创建数据库的连接对象时,所述driveradapter类实例将创建连接的操作委托给被封装的所述驱动类实例,由所述驱动类实例创建连接。

优选的,在执行所述通过所述驱动管理器中注册的driveradpter类实例创建数据库的连接对象时,用户通过调用驱动管理器getconnection方法来创建数据库的连接对象,且创建连接时传入jdbcurl参数给驱动管理器getconnection方法。

第二方面,本发明还提供了一种同一数据库多个版本jdbc驱动共存系统,用于实现第一方面所述的同一数据库多个版本jdbc驱动共存方法,所述系统包括:

动态加载单元,用于通过urlclassloader动态加载驱动类;

动态创建单元,用于通过动态加载的驱动类,动态创建驱动类实例;

封装注册单元,用于使用driveradpter类封装原始的所述驱动类实例以得到driveradpter类实例,并将所述driveradpter类实例注册到驱动管理器;

创建连接单元,用于通过所述驱动管理器中注册的driveradpter类实例创建数据库的连接对象;

注销单元,用于从所述驱动管理器中注销当前的driveradpter类实例,以便进行下个版本驱动的动态加载。

优选的,所述系统还包括:

操作单元,用于通过各连接对象操作对应版本驱动下的数据库;

关闭释放单元,用于对于完成数据库操作的对应版本,关闭并释放对应的连接对象。

本发明的有益效果是:

本发明提供的一种同一数据库多个版本jdbc驱动共存方法和系统中,通过urlclassloader动态加载驱动类,且多个不同的版本分别对应有不同的urlclassloader,并对驱动进行动态注册和注销,实现了同时加载和注册一种数据库多个版本的驱动;同时使用driveradpter类封装驱动类实例,绕过了动态加载类时驱动管理器对于类加载器的限制,从而使java应用可以同时访问一种数据库的不同版本,使同一种数据库的不同版本之间的数据交换和集成得以方便的实现。

【附图说明】

为了更清楚地说明本发明实施例的技术方案,下面将对本发明实施例中所需要使用的附图作简单地介绍。显而易见地,下面所描述的附图仅仅是本发明的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。

图1为本发明实施例提供的jdbc访问数据库的工作原理示意图;

图2为现有的一种使用jdbc访问数据库的方法流程图;

图3为现有的一种使用jdbc访问数据库时jdbc的调用示意图;

图4为本发明实施例提供的一种同一数据库多个版本jdbc驱动共存方法;

图5为本发明实施例提供的多个版本jdbc驱动共存时jdbc的调用示意图;

图6为本发明实施例提供的一种同一数据库多个版本jdbc驱动共存系统的结构组成图。

【具体实施方式】

对于一般的应用系统来说,通常只需要访问一种数据库,此时java应用程序使用jdbc访问数据库的常规流程如图2所示,以访问达梦数据库为例,流程图中各步骤具体如下:

步骤101,通过classpath加载驱动类。

一般的java应用程序主要使用appclassloader来加载驱动类,为静态加载,驱动类相关的jar包是位于应用启动时jvm的classpath上的。以dmdriver表示达梦驱动,dmdriver类实现了jdbc接口java.sql.driver。此处调用class.forname方法来加载,具体语句如下:

class.forname("dm.jdbc.driver.dmdriver");

步骤102,创建驱动类实例并向驱动管理器注册驱动类实例。

在驱动管理器中用一个列表保存了所有已经注册的驱动类实例,同一种数据库的不同版本驱动对应的驱动类名称是相同的,例如达梦6和达梦7,oracle8和oracle10,而静态加载时无法创建两个类名相同但实际实现不同的类对象,因此也就无法将同一数据库不同版本的jdbc驱动注册到驱动管理器drivermanager中。其中,此处注册驱动类实例的语句如下:

drivermanager.registerdriver(newdmdriver());

步骤103,通过驱动管理器中注册的驱动类实例创建连接对象。

该步骤中用户调用drivermanager.getconnection来创建连接,驱动管理器依次调用已经注册的驱动类实例的acceptsurl(stringurl)方法,找到对应的驱动类实例,并利用该驱动类实例创建数据库的连接对象。驱动类实例的类加载器必须也是当前应用程序类的加载器,否则调用创建连接会失败。其中,创建连接的语句如下:

connectionconn=drivermanager.getconnection("jdbc:dm://localhost:5236");

步骤104,通过连接对象操作数据库。

应用程序通过驱动管理器获取到数据库的连接对象后,使用该连接对象调用jdbc接口来操作数据库。该步骤中使用的语句如下:

statementst=connection.createstatement();

st.executeupdate("insertinto....");

上述操作为执行一个insert语句,实际开发中,具体实现与应用需求相关,此处不再赘述。

步骤105,关闭并释放连接对象。

对数据库的操作完成后,将对应的连接对象关闭并释放,该步骤中使用的语句如下:

st.close();

conn.close();

使用上述常规的数据库访问方法时,类加载情况以及调用过程如图3所示,其中实线表示调用关系,虚线表示驱动注册。由图知,应用程序类以及驱动类均由appclassloader加载,驱动管理器的drivermanager类由bootstrapclassloader加载。访问数据库时,应用程序调用drivermanager,drivermanager调用驱动类实例,进而完成对数据库的操作。

由上述步骤可知,传统的数据库访问方法主要用于只访问一种数据库的情况,当同一种数据库的不同版本驱动不兼容时,无法同时访问多个版本。鉴于此,为克服上述问题本发明提出了以下方案。

为了使本发明的目的、技术方案及优点更加清楚明白,以下结合附图及实施例,对本发明进行进一步详细说明。应当理解,此处所描述的具体实施例仅仅用以解释本发明,并不用于限定本发明。

此外,下面所描述的本发明各个实施方式中所涉及到的技术特征只要彼此之间未构成冲突就可以相互组合。下面就参考附图和实施例结合来详细说明本发明。

实施例1:

本发明实施例提供了一种同一数据库多个版本jdbc驱动共存方法,参考图4,具体包括以下步骤:

步骤201,通过urlclassloader动态加载驱动类。

步骤202,通过动态加载的驱动类,动态创建驱动类实例。其中,对于多个不同版本的jdbc驱动,在所述步骤201中,分别使用不同的urlclassloader进行驱动类的加载,以便创建不同版本的驱动类实例。

步骤203,使用driveradpter类封装原始的所述驱动类实例以得到driveradpter类实例,并将所述driveradpter类实例注册到驱动管理器。所述driveradpter类由appclassloader加载,采用driveradpter类封装后可绕过驱动管理器对于类加载器的检查,以成功创建连接。

步骤204,通过所述驱动管理器中注册的driveradpter类实例创建数据库的连接对象。其中,对于多个不同版本的驱动类实例,对应创建的连接对象也不同,用于操作对应版本的数据库。

步骤205,从所述驱动管理器中注销当前的driveradpter类实例,以便进行下个版本驱动的动态加载。对于不同版本的加载创建,即为不断循环重复所述步骤201-205的过程,即每创建一个版本的连接后进行driveradpter类实例的注销,继而对下个版本的驱动重复操作步骤201-205,进行创建连接,直至对所有版本的驱动完成创建连接。

步骤206,通过各连接对象操作对应版本驱动下的数据库。

步骤207,对于完成数据库操作的对应版本,关闭并释放对应的连接对象。对于多个不同版本驱动对应的数据库,对任一数据库的操作完成后,按照匹配结果将对应的连接对象关闭并释放。

本发明实施例提供的一种同一数据库多个版本jdbc驱动共存方法中,通过urlclassloader动态加载驱动类,不同的版本对应不同的urlclassloader,并对驱动进行动态注册和注销,实现了同时加载和注册一种数据库多个版本的驱动;同时使用driveradpter类封装驱动类实例,绕过了动态加载类时驱动管理器对于类加载器的限制,从而使java应用可以同时访问一种数据库的不同版本,使同一种数据库的不同版本之间的数据交换和集成得以方便的实现。

下面就以达梦数据库为例,对各步骤的具体实现方式进行说明。

在步骤201中,通过urlclassloader动态加载驱动类的语句如下:

urlclassloaderclassloader=newurlclassloader(new

file("d:\\dmdbms\drivers\\jdbc\\dm7jdbcdriver.jar").touri().tourl());

class<?>driverclass=

classloader.loadclass("dm.jdbc.driver.dmdriver");

一般应用程序主要使用appclassloader加载驱动类,驱动类相关的jar包是位于classpath上,appclassloader只能加载classpath下面的类,而urlclassloader可以加载任意路径下的类。因此,采用urlclassloader,可实现在应用程序运行过程中通过指定驱动类的路径来动态加载驱动类;其中,所述驱动类实现了jdbc接口java.sql.driver。对于每个不同版本的jdbc驱动,分别使用不同的urlclassloader进行驱动类的加载,以便后续创建不同版本的驱动类实例,进而解决了jvm中不同版本的同名驱动类共存的问题。

在步骤202中,通过动态加载的驱动类来创建驱动类实例的语句如下:

driverdriver=(driver)driverclass.newinstance();

对于不同版本的驱动,其驱动类名相同,但是来自不同的jar包,因此具体实现不同。由于此驱动类是通过urlclassloader动态加载的类,而对于每个不同版本的jdbc驱动分别使用不同的urlclassloader,因此只要加载驱动类的不是同一个urlclassloader,即使其类名相同,也会被jvm认为是不同的类,所以可实现创建不同版本的驱动类实例,即dmdriver对象,而不会互相冲突,也就是说不同版本的dmdriver对象可实现共存。

在步骤203中,使用driveradpter类封装驱动类实例并注册的语句如下:

driverdriveradpter=newdriveradapter(driver);

drivermanager.registerdriver(driveradpter);

在这里,所述driveradpter类与所述驱动类一样实现了java.sql.driver接口,但所述driveradpter类是一个适配器,将接口方法的实现代理给被封装的原始的所述驱动类实例,也就是在步骤202中创建的dmdriver对象。此处采用driveradpter类对原始的驱动类实例进行封装,是为了绕过驱动管理器的类加载器检查机制,以通过驱动管理器对类加载器的检查,从而可顺利创建连接对象,具体将在步骤204中介绍。其中,driveradpter的实现代码如下:

在步骤204中,用户通过调用驱动管理器getconnection方法来创建数据库的连接对象,且创建连接时需传入jdbcurl参数给驱动管理器getconnection方法,创建连接的语句如下:

connectionconn=

drivermanager.getconnection("jdbc:dm://localhost:5236");

在该步骤中,所述驱动管理器调用已经注册的driveradpter类实例的acceptsurl(stringurl)方法;如果acceptsurl(stringurl)方法返回true且通过类加载器的检查,则利用对应的driveradpter类实例创建数据库的连接对象;acceptsurl是jdbc接口定义的,是driveradpter类实例内部的函数。其中,所述驱动管理器中会调用isdriverallowed函数进行类加载器的检查,该函数检查逻辑具体为:使用当前应用程序的类加载器(即appclassloader)来加载原始驱动类(即由urlclassloader动态加载的驱动类),所述驱动管理器检查appclassloader是否能够加载到由urlclassloader动态加载的驱动类,如果不能则报错;如果能则通过对类加载器的检查。

在本发明实施例中,为了实现不同版本的驱动类实例在jvm中共存,使用了urlclassloader来动态加载驱动类,即所述步骤202中的dmdriver对象是通过urlclassloader动态加载并创建的,驱动类jar包不在应用的classpath上。如果在步骤203中不使用driveradpter类封装,而是直接将步骤202中动态创建的dmdriver对象直接注册到驱动管理器,那么,appclassloader无法加载到原始的驱动类(dm.jdbc.driver.dmdriver),所以直接注册原始驱动类实例必然会导致检查失败。为了解决这一问题,在所述步骤203中创建一个driveradpter的类,使用driveradapter类来封装原始的驱动类实例,则向驱动管理器中注册的是driveradapter类的对象;其中,所述driveradpter类由appclassloader加载,所述driveradpter类本身就是位于java虚拟机的classpath路径上的,则用driveradpter类封装原始驱动类后appclassloader可加载到原始的驱动类,从而可通过驱动管理器drivermanager对类加载器的检查,进而可顺利地使用driveradapter创建数据库的连接对象。

driveradpter类实例与被封装的原始的驱动类实例都实现了java.sql.driver接口,因此driveradpter类实例的功能与被封装的原始驱动类实例的功能完全一致。而所述driveradapter类实例将创建连接的操作委托给被封装的原始驱动类实例,即原始的dmdriver对象,由dmdriver对象创建连接,这与直接注册dmdriver对象创建的连接是等效的,可创建与多个版本驱动相对应的多个不同的连接对象。

在步骤205中,从驱动管理器中注销当前的driveradpter类实例的语句如下:drivermanager.deregisterdriver(driveradpter);

由于需要创建多个版本的数据库的连接对象,在动态加载另一个版本的驱动类之前,必须先注销掉驱动管理器中当前的driveradpter类实例,也就是把driveradpter类实例从注册表中移走。因为驱动管理器中是根据jdbcurl选择已注册的驱动对象负责创建数据库连接,而同一数据库不同版本的jdbc驱动url格式一般是相同的,如果不注销后就重新注册新版本的驱动,则驱动管理器可能使用老版本的驱动对象来创建连接,从而导致连接失败。

所述步骤206和步骤207中使用的语句可参考常规的数据库访问步骤,其中,所述步骤206具体参考步骤104,所述步骤207具体参考步骤105,此处不再赘述。

在本发明实施例中,以达梦数据库为例介绍了同一数据库多个版本jdbc驱动共存的方法,上述步骤中给出的是任一版本的驱动的处理过程,当有多个版本的驱动时需重复执行步骤201-205。比如,如果需要同时访问达梦6和达梦7,可先按照上述步骤进行达梦6版本的加载并创建连接,在所述步骤205中将driveradpter类实例注销后,再重复步骤201-205,进行达梦7版本的加载并创建连接;如果有更多版本,以此类推,不断循环重复上述步骤201-205,直至处理完所有版本的驱动,如此一来即可实现不同版本驱动的共同加载。同时,对于其他各种数据库的不同版本,比如oracle8和oracle10,驱动加载过程也均可参考上述过程,此处不再赘述。

通过本发明实施例提供的方法,类加载情况以及调用过程如图5所示,其中实线表示调用关系,虚线表示驱动注册和注销。由图知,应用程序类仍由appclassloader加载,驱动管理器的drivermanager类仍由bootstrapclassloader加载;而驱动类由urlclassloader动态加载,driveradpter类由appclassloader加载。在图示实施例中,同一驱动类下有版本1和版本2两个不同的版本,对应创建有不同版本的drivermanager实例1和drivermanager实例2。访问数据库时,应用程序调用drivermanager,drivermanager可调用两个不同版本的drivermanager实例,drivermanager实例调用对应的驱动类实例,进而完成对同一数据库不同版本驱动的操作。

实施例2:

在上述实施例1的基础上,本发明实施例还提供了一种同一数据库多个版本jdbc驱动共存系统,参考图6,所述系统包括:

动态加载单元1,用于通过urlclassloader动态加载驱动类。采用urlclassloader,可实现在应用程序运行过程中通过指定驱动类的路径来动态加载驱动类;其中,对于每个不同版本的jdbc驱动,分别使用不同的urlclassloader进行驱动类的加载,以便后续创建不同版本的驱动类实例,进而解决了jvm中不同版本的同名驱动类共存的问题。

动态创建单元2,用于通过动态加载的驱动类,动态创建驱动类实例。由于驱动类是通过urlclassloader动态加载的类,只要加载驱动类的不是同一个urlclassloader,即使其类名相同,也会被jvm认为是不同的类,所以可实现创建不同版本的驱动类实例,不同版本的dmdriver对象可实现共存,而不会互相冲突。

封装注册单元3,用于使用driveradpter类封装原始的所述驱动类实例以得到driveradpter类实例,并将所述driveradpter类实例注册到驱动管理器。其中,所述driveradpter类与驱动类一样实现了java.sql.driver接口,但所述driveradpter类将接口方法的实现代理给被封装的驱动对象。所述driveradpter类由appclassloader加载,采用driveradpter类对原始的驱动类实例进行封装,可绕过驱动管理器的类加载器检查机制,从而顺利创建连接对象。

创建连接单元4,用于通过所述驱动管理器中注册的driveradpter类实例创建数据库的连接对象。其中,所述驱动管理器调用已经注册的driveradpter类实例的acceptsurl(stringurl)方法;如果该方法返回true且通过类加载器的检查,则利用对应的driveradpter类实例创建数据库的连接对象。对于多个不同版本的驱动类实例,对应创建的连接对象也不同。

注销单元5,用于从所述驱动管理器中注销当前的driveradpter类实例,以便进行下个版本驱动的动态加载。由于需要创建多个版本的数据库的连接对象,在动态加载另一个版本的驱动类之前,必须先注销掉驱动管理器中当前的driveradpter类实例;如果不注销后重新注册新版本的驱动,则驱动管理器可能使用老版本的驱动对象来创建连接,导致连接失败;

操作单元6,用于通过各连接对象操作对应版本驱动下的数据库。应用程序通过驱动管理器获取到数据库对应的连接对象后,便使用该连接对象调用jdbc接口来操作数据库;

关闭释放单元7,用于对于完成数据库操作的对应版本,关闭并释放对应的连接对象。

本发明实施例提供的一种同一数据库多个版本jdbc驱动共存系统中,通过动态加载单元、动态创建单元、封装注册单元以及注销单元的配合,可使用不同的urlclassloader动态加载驱动类的不同版本,实现了同时加载和注册一种数据库多个版本的驱动;同时使用driveradpter类封装驱动类实例,绕过了动态加载类时驱动管理器对于类加载器的限制,从而使java应用可以同时访问一种数据库的不同版本,使不同版本之间的数据交换和集成得以方便的实现。

以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的保护范围之内。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1