Spark 无法从 SBT 找到 JDBC 驱动程序

Posted

技术标签:

【中文标题】Spark 无法从 SBT 找到 JDBC 驱动程序【英文标题】:Spark Can't Find JDBC Driver from SBT 【发布时间】:2017-07-21 00:30:24 【问题描述】:

我正在尝试在 Scala Spark 应用程序中使用 JDBC,并且正在使用 sbt 进行编译。但是,当我添加行 Class.forName("com.mysql.jdbc.Driver") 时,它会引发 ClassNotFoundException。

我的 sbt 文件是这样的:

name := "SparkApp"
version := "1.0"
scalaVersion := "2.11.8"
libraryDependencies += "org.apache.spark" %% "spark-core" % "2.1.0"
libraryDependencies += "org.apache.spark" %% "spark-sql" % "2.1.0"
libraryDependencies += "com.databricks" %% "spark-csv" % "1.5.0"
libraryDependencies += "org.apache.spark" %% "spark-mllib" % "2.1.0"
libraryDependencies += "mysql" % "mysql-connector-java" % "6.0.5"

据我所知,最后一行是添加 JDBC 驱动程序所需的全部内容,但它似乎不起作用。我也尝试过Class.forName("com.mysql.jdbc.Driver").newInstance(),但结果相同,所以我认为问题在于根本没有正确添加 jdbc 类。

【问题讨论】:

【参考方案1】:

您无需提供类名即可使用 JDBC 加载数据帧。在Spark SQL documentation 之后,您只需提供"jdbc" 作为数据源格式(并且确实将连接器添加为依赖项)并设置正确的选项:

val host: String = ???
val port: Int = ???
val database: String = ???
val table: String = ???
val user: String = ???
val password: String = ???

val options = Map(
      "url" -> s"jdbc:mysql://$host:$port/$database?zeroDateTimeBehavior=convertToNull",
      "dbtable" -> table,
      "user" -> user,
      "password" -> password)

val df = spark.read.format("jdbc").options(options).load()

当您将应用程序提交到 Spark 时,您必须将 MySQL 连接器包含到您的最终 jar 文件中,或者告诉spark-submit 将包作为依赖项获取:

spark-submit --packages mysql:mysql-connector-java:6.0.5 ...

此标志也适用于 spark-shellpyspark

【讨论】:

写入数据库怎么样?我的最终目标是获取我拥有的 DataFrame 并将其写入 MySQL 中的表中。我尝试这样做,但出现“没有合适的驱动程序”错误:val prop = new java.util.Properties() prop.setProperty("user", "username") prop.setProperty("password", "password") dataFrame.write.mode("append").jdbc("jdbc:mysql://localhost:3306/database", "table", prop) 写作应该类似地工作,使用相同的选项。你如何运行你的代码?如果您提交它,请参阅我的编辑以确保依赖项可用。 添加了 packages 参数,这似乎解决了驱动程序问题。最初给出了一个已弃用的错误,但我只需要更改为com.mysql.cj.jdbc.Driver。本来以为 sbt 依赖就足够了。谢谢!【参考方案2】:

您的 mysql 驱动程序类 com.mysql.jdbc.Driver 它在运行时不存在于您的类路径中。如果您使用 spark-submit 运行 Spark 作业,那么您至少有两个选择:

提供 --jar 选项来指定 mysql-*.jar 的路径(参见 post)(如果工作人员和驱动程序都需要该类,请仔细查看 spark.executor.extraJavaOptions 和 spark.driver.extraJavaOptions) 构建一个 uber jar(fat jar),它将在您的应用程序 jar 中包含您的 mysql-* 类(参见 post)

【讨论】:

【参考方案3】:

spark-submit \ --class com.mypack.MyClass \ --master yarn --deploy-mode cluster \ --conf spark.executor.extraClassPath=$POSTGRESQL_JAR_PATH:$MYSQL_JAR_PATH \ --conf spark.driver.extraClassPath=$POSTGRESQL_JAR_PATH:$MYSQL_JAR_PATH \

其中,$POSTGRESQL_JAR_PATH$MYSQL_JAR_PATH 应设置为 jar 文件的 hdfs 路径。

希望这会有所帮助。

spark.executor.extraClassPath 如果您在集群模式下运行它。 spark.driver.extraClassPath 如果您在本地运行它。

我建议将这两个选项设置为更安全。

【讨论】:

【参考方案4】:

您应该在提交 spark 作业时传递驱动程序 jar,如下所示:

1) spark-submit --jars mysql-connector-java-5.1.39.jar 和您传递的其余参数

2) 如果你只是想在本地尝试使用 shell spark-shell --jars mysql-connector-java-5.1.39.jar

将驱动程序更新到您已有的驱动程序并提供该驱动程序的绝对路径

【讨论】:

以上是关于Spark 无法从 SBT 找到 JDBC 驱动程序的主要内容,如果未能解决你的问题,请参考以下文章

Apache spark JDBC连接读写驱动程序丢失

如何在 SBT Scala 项目中使用 MySQL JDBC 驱动程序?

[XXX] 注册了JDBC驱动程 序 [oracle.jdbc.OracleDriver]

在 Spark 中使用 jdbc 驱动程序连接到 Hive

spark和aws redshift:java.sql.SQLException:没有找到适合jdbc的驱动程序:redshift://xxx.us-west-2.redshift.amazonaws

从 Spark 到雪花的连接