You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

sbt-assembly打包Scala项目缺失PostgreSQL JDBC驱动解决方案

问题描述

我有一个Scala项目,通过JDBC连接PostgreSQL数据库取数,使用IntelliJ配合SBT构建,借助sbt-assembly插件打包成包含所有依赖的单JAR包。在IntelliJ内运行程序完全正常,但执行以下命令时抛出异常:

java -jar /opt/service/sample.jar

异常信息:

Exception in thread "main" java.sql.SQLException: java.sql.SQLException: No suitable driver found for jdbc:postgresql://

解压生成的JAR包后,未找到PostgreSQL驱动相关文件,推测是sbt-assembly未将该依赖打包进JAR。本地通过指定额外依赖的方式执行命令,程序能正常运行:

java -cp sampl.jar:/Users/x/.m2/repository/org/postgresql/postgresql/42.2.7/postgresql-42.2.7.jar com.abc.main

以下是项目中build.sbt的assembly相关配置,需要修改配置让单JAR包无需额外依赖即可运行:

ThisBuild / libraryDependencies ++= Seq(
  "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2",
  "org.postgresql" % "postgresql" % "42.2.14"
)

import sbtassembly.MergeStrategy
assemblyMergeStrategy in assembly := {
  case PathList("org", "apache", xs @ _*) => MergeStrategy.first
  case PathList("org", "slf4j", xs @ _*) => MergeStrategy.first
  case PathList("org", "aopalliance", xs @ _*) => MergeStrategy.first
  case PathList("jersey", "repackaged", xs @ _*) => MergeStrategy.first
  case PathList("javax", xs @ _*) => MergeStrategy.first
  case PathList("io", "netty", xs @ _*) => MergeStrategy.first
  case PathList("com", "amazonaws", xs @ _*) => MergeStrategy.first
  case PathList("META-INF", xs @ _*) =>
    (xs map {_.toLowerCase}) match {
      case ("manifest.mf" :: Nil) | ("index.list" :: Nil) | ("dependencies" :: Nil) => MergeStrategy.discard
      case _ => MergeStrategy.first
    }
  case PathList("com", "sun", xs @ _*) => MergeStrategy.first
  case PathList("git.properties", xs @ _*) => MergeStrategy.first
  case PathList("mozilla", xs @ _*) => MergeStrategy.first
  case x =>
    val oldStrategy = (assemblyMergeStrategy in assembly).value
    oldStrategy(x)
}
解决方案

修改后的build.sbt配置如下,主要调整两点:确保PostgreSQL驱动被纳入打包范围,以及正确处理驱动的服务注册文件避免丢失:

ThisBuild / libraryDependencies ++= Seq(
  "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2",
  // 显式声明compile范围,确保驱动被打包进最终JAR
  "org.postgresql" % "postgresql" % "42.2.14" % Compile
)

import sbtassembly.MergeStrategy
assemblyMergeStrategy in assembly := {
  // 新增PostgreSQL路径的合并策略,避免驱动文件被意外排除
  case PathList("org", "postgresql", xs @ _*) => MergeStrategy.first
  case PathList("org", "apache", xs @ _*) => MergeStrategy.first
  case PathList("org", "slf4j", xs @ _*) => MergeStrategy.first
  case PathList("org", "aopalliance", xs @ _*) => MergeStrategy.first
  case PathList("jersey", "repackaged", xs @ _*) => MergeStrategy.first
  case PathList("javax", xs @ _*) => MergeStrategy.first
  case PathList("io", "netty", xs @ _*) => MergeStrategy.first
  case PathList("com", "amazonaws", xs @ _*) => MergeStrategy.first
  case PathList("META-INF", xs @ _*) =>
    (xs map {_.toLowerCase}) match {
      case ("manifest.mf" :: Nil) | ("index.list" :: Nil) | ("dependencies" :: Nil) => MergeStrategy.discard
      // 合并JDBC驱动的服务注册文件,保证自动加载生效
      case ("services" :: "java.sql.Driver" :: Nil) => MergeStrategy.concat
      case _ => MergeStrategy.first
    }
  case PathList("com", "sun", xs @ _*) => MergeStrategy.first
  case PathList("git.properties", xs @ _*) => MergeStrategy.first
  case PathList("mozilla", xs @ _*) => MergeStrategy.first
  case x =>
    val oldStrategy = (assemblyMergeStrategy in assembly).value
    oldStrategy(x)
}

额外注意:如果你的JDBC连接代码没有显式加载驱动类Class.forName("org.postgresql.Driver"),则必须确保META-INF/services/java.sql.Driver文件被正确打包(上面的配置已经通过MergeStrategy.concat处理了该文件的合并,避免被其他依赖的同名文件覆盖)。

修改完成后,重新执行sbt assembly生成新的JAR包,再运行java -jar /opt/service/sample.jar即可正常连接数据库。

内容的提问来源于stack exchange,提问作者Siddarth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 18:06:01