【问题标题】:Using both Hive and MySql JDBC drivers同时使用 Hive 和 MySql JDBC 驱动程序
【发布时间】:2017-03-01 08:37:17
【问题描述】:

TL;DR: Hive 和 MySql JDBC 一起使用会不会有问题?

我正在开发一个应用程序,该应用程序使用 MySql JDBC 驱动程序执行多个 SQL 查询,然后它还使用 Hive JDBC 发送另一个 Hive 查询。

现在发生的事情是 MySql 查询正常工作,当代码尝试执行 Hive 查询时,它会抛出此异常:

com.mysql.cj.core.exceptions.WrongArgumentException: Connector/J cannot handle a database URL of type 'jdbc:hive2:'.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.cj.core.exceptions.ExceptionFactory.createException(ExceptionFactory.java:54)
    at com.mysql.cj.core.conf.url.ConnectionUrl$Type.fromValue(ConnectionUrl.java:149)
    at com.mysql.cj.core.conf.url.ConnectionUrl.getConnectionUrlInstance(ConnectionUrl.java:193)
    at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:195)
    at java.sql.DriverManager.getConnection(DriverManager.java:664)
    at java.sql.DriverManager.getConnection(DriverManager.java:247)
    at company.services.HiveV2Provider.createConnection(HiveProvider.scala:105)
    at company.services.HiveProvider$class.loanConnection(HiveProvider.scala:66)

现在抛出此异常后,查询将正确执行。

我的猜测是,由于我同时加载了 MySql 和 Hive 驱动程序,MySql 驱动程序首先尝试运行此查询,但是当它遇到 Hive URL 时会抛出此异常,然后 Hive 驱动程序会看到它并执行正确查询

这就是我执行 MySql 代码的方式:

val query = ... // query is created here
var mysqlConn: Connection = null
var stmt: Statement = null
try {
  Class.forName("com.mysql.jdbc.Driver")
  mysqlConn = DriverManager.getConnection(mysqlAddress, username, password)
  stmt = mysqlConn.createStatement()
  val rs = stmt.executeQuery(query)
  val returnVal = someResultSetHandlingFunction(rs)
  rs.close()
  returnVal
} catch {
  case NonFatal(e) =>
    logWarning(s"Failed to execute query on: $mysqlAddress", e)
    throw e
} finally {
  if (mysqlConn != null) {
    mysqlConn.close()
  }
}

我的 Hive 代码看起来相同,只是驱动程序名称为:org.apache.hive.jdbc.HiveDriver(它与 jdbc:hive2://someurl 通信)

版本:

  • Hive 是 hive-jdbc-1.1.0-cdh5.7.1
  • MySql 是 mysql-connector-java 6.0.4

有人知道是否有任何方法可以避免收到此异常吗?加载 2 个不同的 JDBC 驱动程序是否有问题?阅读其他一些类似的问题,我觉得这应该不是问题

只是一些澄清:

  • 我知道直接使用 JDBC 可能不是最好的方法,但我正在检查一些东西,JDBC 适合这项任务
  • 我正在使用 Scala,但我认为这对于这个问题并不重要

提前致谢

【问题讨论】:

    标签: mysql scala jdbc hive


    【解决方案1】:

    我差点忘了回答我的问题

    所以这个问题可能与this 错误有关。当我遇到这个问题时,我没有注意到它只是一个堆栈跟踪打印,而不是一个实际的失败,所以它的问题比我预期的要少。

    无论如何,然后我看到在某些特定版本中,此问题已修复,如您所见 here 所以我只是将我的 mysql 版本更改为 5.1.9(因为我不需要更高版本的任何特定内容)和堆栈跟踪失败消失了。

    如果有人对此有更优雅的解决方案,我会很高兴

    干杯

    【讨论】:

    • 我正在评论我的解决方案(对 SQLServer 驱动程序,同样的错误),但答案太长了。作为另一个答案发布。也许它也适合 Hive 驱动程序。
    • 我显然已经让它工作了,但是由于这些问题调试起来很烦人,我希望你的回答也可以帮助未来的开发人员:)
    【解决方案2】:

    我在使用 MS SQL Server JDBC 驱动程序时遇到了同样的问题。记录了相同的错误,但一切正常。

    根据this Microsoft page:

    在 JDBC API 4.0 中,DriverManager.getConnection 方法是 增强以自动加载 JDBC 驱动程序。因此,应用 不需要调用 Class.forName 方法来注册或加载 使用 sqljdbc4.jar、sqljdbc41.jar 或 sqljdbc42.jar 时的驱动程序 类库。

    所以我尝试删除 Class.forName 并直接调用 DriverManager.getConnection。一切正常,我不再收到烦人的错误。

    我相信驱动程序本身必须包含一个“META-INF/services/java.sql.Driver”文件,该文件将自己注册为有效的 JDBC 驱动程序,因此不一定对您有用,但对于 SQL Server 驱动程序用户来说,它是要走的路。

    顺便说一句:我注意到 DriverManager.getConnection 在第一次调用驱动器时需要更多时间(6 或 7 秒)来加载驱动器。后续调用正常。根据您的应用程序,这可能是个问题。

    【讨论】:

      【解决方案3】:
      Class.forName("com.mysql.jdbc.Driver")
      

      将在 DriverManager 中注册您的 JDBC 驱动程序。然后你把 hive 连接 uri 放在

      DriverManager.getConnection(mysqlAddress, username, password) 
      

      在这种情况下会出现异常。

      在检查 uri 之后为什么不将调用委托给特定的 JDBC 驱动程序:

         if (uri.contains("hive")){
             //call Hive JDBC
          }
      
          else if (uri.contains("mysql")){
             //call Mysql JDBC
          }
      

      【讨论】:

      • 感谢您的回复,但是我打错了,我的意思是我的 Hive JDBC 代码使用了不同的驱动程序名称(我更新了问题)所以是的,我在发送之前加载了正确的 HiveDriver Hive 请求
      • 我有 2 个问题 - 1. 你能单独使用它们中的每一个吗? 2.您的代码流是否分开意味着hive连接uri不会转到try {Class.forName("com.mysql.jdbc.Driver")代码块?
      • 1.是的,他们都分开工作。即使现在,当它们一个接一个地使用时,它们也会抛出异常,但它们仍然可以工作。我只是不喜欢在运行我的代码时看到异常 2. 流代码是分开的。这是 2 个完全不同的类,所以 URI 不可能进入 try 块
      猜你喜欢
      • 2020-05-22
      • 1970-01-01
      • 2012-07-20
      • 2011-09-10
      • 2016-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-24
      相关资源
      最近更新 更多