jaydebeapi 同时连接两种数据库

在使用jaydebeapi只连接一种数据库时,是没问题的,但是如果需要同时连接两种数据库,比如同时连接oracle和mysql

例如以下测试代码:

  1.  
    import jaydebeapi ##使用jdbc驱动连接数据库
  2.  
    import pandas as pd
  3.  
     
  4.  
    dirver='oracle.jdbc.driver.OracleDriver'
  5.  
    jarFile='D:\\WORK\\PYScript\\BiDataMonitor\\jdbc\\64\\ojdbc14.jar'
  6.  
    addr_='xxx.xxx.xxx.xxx'+':'+'1521'+'/'+'xxx'
  7.  
    url='jdbc:oracle:thin:@'+addr_
  8.  
    print('url',url)
  9.  
    DBUser='用户名'
  10.  
    DBPwd='密码'
  11.  
    conn=jaydebeapi.connect(dirver,[url,DBUser,DBPwd],jarFile) ##使用jdbc驱动连接数据库
  12.  
    sql_str="select 'oracle' from dual"
  13.  
    df=pd.read_sql_query(sql_str,conn)
  14.  
    print(df)
  15.  
    conn.close()
  16.  
     
  17.  
     
  18.  
    dirver='com.mysql.jdbc.Driver'
  19.  
    jarFile='D:\\WORK\\PYScript\\BiDataMonitor\\jdbc\\64\\mysql-connector-java-5.1.30.jar'
  20.  
    addr_='xxx.xxx.xxx.xxx'+':'+'3306'+'/'+'xxx'
  21.  
    url='jdbc:mysql://'+addr_
  22.  
    print('url',url)
  23.  
    DBUserMySql='用户名'
  24.  
    DBPwdMySql='密码'
  25.  
    conn2=jaydebeapi.connect(dirver,[url,DBUserMySql,DBPwdMySql],jarFile)
  26.  
    sql_str="select 'mysql' from dual"
  27.  
    df=pd.read_sql_query(sql_str,conn2)
  28.  
    print(df)
  29.  
    conn2.close()

在连接第二种数据库时,就会报错误:

  1.  
    Py4JJavaError: An error occurred while calling z:java.sql.DriverManager.getConnection.
  2.  
    : java.sql.SQLException: No suitable driver found for jdbc:mysql://10.1.164.5:3306/vvm
  3.  
    at java.sql.DriverManager.getConnection(Unknown Source)
  4.  
    at java.sql.DriverManager.getConnection(Unknown Source)
  5.  
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  6.  
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  7.  
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  8.  
    at java.lang.reflect.Method.invoke(Unknown Source)
  9.  
    at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244)
  10.  
    at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
  11.  
    at py4j.Gateway.invoke(Gateway.java:282)
  12.  
    at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
  13.  
    at py4j.commands.CallCommand.execute(CallCommand.java:79)
  14.  
    at py4j.GatewayConnection.run(GatewayConnection.java:214)
  15.  
    at java.lang.Thread.run(Unknown Source)

错误信息中显示,找不到渠道,而实际上并不是驱动或者jar包的问题。

要分析和解决这个问题,还需要从jaydebeapi的源码中分析,打开jaydebeapi源码(下载地址:https://pypi.python.org/pypi/JayDeBeApi3),从报错信息中我们可以得到,是在...jaydebeapi\__init__.py", line 68

jaydebeapi.connect方法源码如下:

  1.  
    # DB-API 2.0 Module Interface connect constructor
  2.  
    def connect(jclassname, driver_args, jars=None, libs=None):
  3.  
    """Open a connection to a database using a JDBC driver and return
  4.  
    a Connection instance.
  5.  
     
  6.  
    jclassname: Full qualified Java class name of the JDBC driver.
  7.  
    driver_args: Argument or sequence of arguments to be passed to the
  8.  
    Java DriverManager.getConnection method. Usually the
  9.  
    database URL. See
  10.  
    http://docs.oracle.com/javase/6/docs/api/java/sql/DriverManager.html
  11.  
    for more details
  12.  
    jars: Jar filename or sequence of filenames for the JDBC driver
  13.  
    libs: Dll/so filenames or sequence of dlls/sos used as shared
  14.  
    library by the JDBC driver
  15.  
    """
  16.  
     
  17.  
    if _gateway_is_running():
  18.  
    gateway = java_gateway.JavaGateway()
  19.  
    else:
  20.  
    driver_args = [driver_args] if isinstance(driver_args, str) else driver_args
  21.  
     
  22.  
    if jars:
  23.  
    classpath = os.pathsep.join(jars) if isinstance(jars, list) else jars
  24.  
    else:
  25.  
    classpath = None
  26.  
     
  27.  
    if libs:
  28.  
    javaopts = libs if isinstance(libs, list) else [libs]
  29.  
    else:
  30.  
    javaopts = []
  31.  
     
  32.  
    gateway = java_gateway.JavaGateway.launch_gateway(
  33.  
    port=25333, classpath=classpath, javaopts=javaopts, die_on_exit=True)
  34.  
     
  35.  
    java_gateway.java_import(gateway.jvm, 'java.sql.DriverManager')
  36.  
    gateway.jvm.Class.forName(jclassname)
  37.  
     
  38.  
    connection = gateway.jvm.DriverManager.getConnection(*driver_args)
  39.  
    if _converters is None:
  40.  
    types_map = {}
  41.  
    for type in gateway.jvm.Class.forName("java.sql.Types").getFields():
  42.  
    types_map[type.getName()] = type.getInt(None)
  43.  
    _init_converters(types_map)
  44.  
     
  45.  
    return Connection(connection, _converters)

报错信息中提示的68行也就是:

connection = gateway.jvm.DriverManager.getConnection(*driver_args)

其实,我不需要跟深层次是剖析,只需要分析下jaydebeapi.connect方法即可,该方法大概是逻辑是:

  1.  
    判断 java_gateway是否running
  2.  
                |----------是---|-----否-----|
  3.  
                | |
  4.  
    获取gateway实例     1、初始化参数
  5.  
        2、创建gateway实例

问题就出在这里,第一次连接oracle时,通过右边分支先初始化参数,然后创建了gateway实例,但是第二次调用jaydebeapi.connect方法连mysql时,由于_gateway_is_running()返回真,所以走左边分支,直接获取了上一次连接oracle时创建gateway实例,其中最重要的两个个参数jclassname和classpath,也就是“oracle.jdbc.driver.OracleDriver”和"ojdbc14.jar"

  1.  
    gateway = java_gateway.JavaGateway.launch_gateway(
  2.  
    port=25333, classpath=classpath, javaopts=javaopts, die_on_exit=True)
  3.  
     
  4.  
    java_gateway.java_import(gateway.jvm, 'java.sql.DriverManager')
  5.  
    gateway.jvm.Class.forName(jclassname)

而第二次连mysql时,用的是mysql的连接,所以当然就是报No suitable driver found for jdbc错误。

明白了报错的原因,下面就来需求解决方法

解决的方法应该有多种,我这里采取了最简单,最暴力的方法,就是在判断_gateway_is_running()时,将其关闭,然后重新重建新的gateway实例,这样虽然简单,但是如果频繁连接数据库时,就会因为不能重用上一次实例而消耗额外的资源。

通过帮助函数可知,gateway实例有一个shutdown方法

修改后的connect方法如下:

  1.  
    # DB-API 2.0 Module Interface connect constructor
  2.  
    def connect(jclassname, driver_args, jars=None, libs=None):
  3.  
    """Open a connection to a database using a JDBC driver and return
  4.  
    a Connection instance.
  5.  
     
  6.  
    jclassname: Full qualified Java class name of the JDBC driver.
  7.  
    driver_args: Argument or sequence of arguments to be passed to the
  8.  
    Java DriverManager.getConnection method. Usually the
  9.  
    database URL. See
  10.  
    http://docs.oracle.com/javase/6/docs/api/java/sql/DriverManager.html
  11.  
    for more details
  12.  
    jars: Jar filename or sequence of filenames for the JDBC driver
  13.  
    libs: Dll/so filenames or sequence of dlls/sos used as shared
  14.  
    library by the JDBC driver
  15.  
    """
  16.  
     
  17.  
    if _gateway_is_running():
  18.  
    gateway = java_gateway.JavaGateway()
  19.  
    gateway.shutdown()
  20.  
    else:
  21.  
    pass
  22.  
    driver_args = [driver_args] if isinstance(driver_args, str) else driver_args
  23.  
     
  24.  
    if jars:
  25.  
    classpath = os.pathsep.join(jars) if isinstance(jars, list) else jars
  26.  
    else:
  27.  
    classpath = None
  28.  
     
  29.  
    if libs:
  30.  
    javaopts = libs if isinstance(libs, list) else [libs]
  31.  
    else:
  32.  
    javaopts = []
  33.  
     
  34.  
    gateway = java_gateway.JavaGateway.launch_gateway(
  35.  
    port=25333, classpath=classpath, javaopts=javaopts, die_on_exit=True)
  36.  
     
  37.  
    java_gateway.java_import(gateway.jvm, 'java.sql.DriverManager')
  38.  
    gateway.jvm.Class.forName(jclassname)
  39.  
     
  40.  
    connection = gateway.jvm.DriverManager.getConnection(*driver_args)
  41.  
    if _converters is None:
  42.  
    types_map = {}
  43.  
    for type in gateway.jvm.Class.forName("java.sql.Types").getFields():
  44.  
    types_map[type.getName()] = type.getInt(None)
  45.  
    _init_converters(types_map)
  46.  
     
  47.  
    return Connection(connection, _converters)

然后卸载jaydebeapi,用修改后的源码重新安装一次即可,源码安装方法,可以查看之前的一篇博客:

https://blog.csdn.net/cakecc2008/article/details/79073181

[转帖]使用JAYDEBEAPI同时连接两个不同数据库(ORACLE+MYSQL)的问题的更多相关文章

  1. Linq to Entity中连接两个数据库时要注意的问题

    Linq to Entity中连接两个数据库时要注意的问题 今天大学同学问了我一个问题,Linq to Entity中连接两个数据库时,报错“指定的 LINQ 表达式包含对与不同上下文关联的查询的引用 ...

  2. Springboot配置连接两个数据库

    背景: 项目中需要从两个不同的数据库查询数据,之前实现方法是:springboot配置连接一个数据源,另一个使用jdbc代码连接. 为了改进,现在使用SpringBoot配置连接两个数据源 实现效果: ...

  3. JavaScript concat() 方法-连接两个或多个数组

    一,定义和用法 concat() 方法用于连接两个或多个数组. 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本. 语法 arrayObject.concat(arrayX,arrayX,. ...

  4. Android 通过外键连接两个数据库

    Learn: 1.Android数据库的语法. 2.通过外键连接两个数据库. 3.加强了对数据库的熟悉度. 4.对文本框的visiblity属性的了解. Demo:http://pan.baidu.c ...

  5. DirectX:函数连接两个随机filter

    函数连接两个随机filter HRESULT ConnectFilters( IBaseFilter *pSrc, IBaseFilter *pDest ) { IPin *pIn = 0; IPin ...

  6. mysql 连接两列

    以下划线符号,连接两列,作为查询结果: SELECT CONCAT(col_1,'_',col_2) FROM yourtable

  7. 连接两个点云中的字段或数据形成新点云以及Opennni Grabber初识

    (1)学习如何连接两个不同点云为一个点云,进行操作前要确保两个数据集中字段的类型相同和维度相等,同时了解如何连接两个不同点云的字段(例如颜色 法线)这种操作的强制约束条件是两个数据集中点的数目必须一样 ...

  8. [转载]INNER JOIN连接两个表、三个表、五个表的SQL语句

    SQL INNER JOIN关键字表示在表中存在至少一个匹配时,INNER JOIN 关键字返回行. 1.连接两个数据表的用法: FROM Member INNER JOIN MemberSort O ...

  9. 怎么用ChemDraw连接两个结构片段

    作为最新版的ChemOffice 15.1的核心组件,ChemDraw几乎能解决所有平面化学结构中的绘制问题.如果用户想连接两个分开的结构片段,ChemDraw提供两种连接两个化学结构片段的方法,分别 ...

  10. 这样才能使本地Mysql服务允许被外部主机连接(两步)

    网上的N多方法都不全面,只有下面的第一步或第二步是不行的,必须同时执行下面两步操作: 修改mysql.user表 以root或debian-sys-maint身份登录mysql $ mysql -u ...

随机推荐

  1. .NET技术分享日活动-202202

    2022年02月19日下午,个人组织举办了山东地区的第四次.NET技术分享日活动.主要包含.NET常用技术.低代码.大前端.大数据和工作流等五个技术领域. 本次技术分享日活动面向了山东地区广大的.NE ...

  2. 性能达1.5+倍!昇腾AI助力分子动力学模拟研究

    摘要:在异构计算架构CANN的助力下,AI预测性能达到现有产品的1.5+倍,可预测规模较传统方法提升10000+倍,为光伏材料.新能源电池.半导体材料研究带来巨大的商业应用价值. 本文分享自华为云社区 ...

  3. npm install过程中遇到typings deprecated的warning该怎么处理

    摘要:在项目里进行npm install操作的时候,发现typings.json文件里的一些定义文件爆出了已经弃用的警告,怎么办? 本文分享自华为云社区<npm install过程中遇到typi ...

  4. 云小课|教你如何使用RDS for PostgreSQL插件

    摘要:本文介绍RDS for PostgreSQL支持的插件及不同插件的创建.删除或使用方法. 本文分享自华为云社区<[云小课][第42课]RDS for PostgreSQL插件介绍>, ...

  5. 云小课|云小课带你快速掌握云数据迁移CDM

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:欢迎来到云数据迁移 ...

  6. Walrus 入门教程:如何创建模板以沉淀可复用的团队最佳实践

    模板是 Walrus 的核心功能之一,模板创建完成后用户可以重复使用,并在使用过程中逐渐沉淀研发和运维团队的最佳实践,进一步简化服务及资源的部署.用户可以使用 HCL 语言自定义创建模板,也可以一键复 ...

  7. 火山引擎DataTester分享:A/B实验中常见的8个错误

    火山引擎DataTester是科学可信的A/B测试与智能优化平台,源自字节跳动长期沉淀,能够深度耦合推荐.广告.搜索.UI.产品功能等多种行业场景需求,为业务增长.转化.产品迭代,运营提效等各环节提供 ...

  8. 直播预告 | 企业如何轻松完成数据治理?火山引擎 DataLeap 给你一份实战攻略!

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 企业数字化转型正席卷全球,这不仅是趋势所在,也是企业发展必然面对的考题,也是企业最关心.最难决策的难题,数字化不仅 ...

  9. ADB移动端及Monkey常用命令

    ADB ADB全程Android Debug Bridge,是android sdk里的一个工具,用这个工具可以直接操作管理android模拟器或者真实的android设备 它的主要功能: 运行设备的 ...

  10. JMeter 源码解读 - HashTree

    背景: 在 JMeter 中,HashTree 是一种用于组织和管理测试计划元素的数据结构.它是一个基于 LinkedHashMap 的特殊实现,提供了一种层次结构的方式来存储和表示测试计划的各个组件 ...