使用Hive和MySql JDBC驱动程序

时间:2016-10-19 15:35:06

标签: mysql scala jdbc hive

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,但我不认为这个问题很重要

提前致谢

3 个答案:

答案 0 :(得分:1)

我差点忘了回答我的问题

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

无论如何,我看到在某些特定版本中这个问题已得到修复,因为你可以看到here所以我只是将我的mysql版本改为5.1.9(因为我不需要更高版本的任何特定的并且堆栈跟踪失败消失了。

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

干杯

答案 1 :(得分:1)

我遇到了与MS SQL Server JDBC Driver相同的问题。记录了同样的错误,但一切正常。

根据this Microsoft page:

  

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

所以我尝试删除Class.forName,然后调用DriverManager.getConnection。事情正在发挥作用,我不再感到烦人的错误了。

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

BTW:我注意到DriverManager.getConnection在第一次调用Drive时需要更多的时间(6或7秒)才能加载Drive。后续调用没问题。根据您的应用程序,这可能是一个问题。

答案 2 :(得分:0)

Class.forName("com.mysql.jdbc.Driver")

将在DriverManager中注册JDBC驱动程序。然后将 hive connection uri 放在

DriverManager.getConnection(mysqlAddress, username, password) 

在这种情况下,预计会出现例外情况。

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

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

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