【问题标题】:How can I make my Apache Derby database work when I run my generated jar file?运行生成的 jar 文件时,如何使 Apache Derby 数据库正常工作?
【发布时间】:2021-09-27 10:26:36
【问题描述】:

我创建了一个 JavaFX 应用程序,并有一个生成的 Jar 文件(使用 Gradle 生成)将启动。

当应用程序启动时,它并没有连接到嵌入式数据库。我觉得好像我错过了一些非常简单的东西,但经过大量研究,我无法弄清楚。从命令提示符运行 jar 文件时,出现以下错误: java.lang.ClassNotFoundException: org.apache.derby.jdbc.EmbeddedDriver

从我所做的阅读中,我知道我可以将它添加到我的类路径中,但经过多次尝试后我没有成功,我已经让这个应用程序在另一台计算机上运行。这可能的,对吧?

如果可能的话,我很想更改我的 build.gradle 文件中的某些内容或将 .jar 包含在一个文件夹中或类似的东西,这对于运行程序的人来说会变得简单。程序大小不是几千兆字节的问题。

【问题讨论】:

    标签: java javafx jar derby


    【解决方案1】:

    你有两个问题

    • 驱动程序类不在您的应用 jar 中
    • 如果您将该数据库嵌入到应用程序 jar 中,您将无法对其进行写入

    你可以做一个“胖罐子”,但这并不能解决第二个问题。你真的需要 an installer 来做到这一点,以便将 db 留在文件系统中,以便可以写入。

    【讨论】:

    • 我没有尝试将数据库嵌入到 .jar 文件中;我知道 jar 文件不可编辑。我只是希望将数据库放在文档文件夹或类似文件夹中。我不在乎数据库在启动时创建的位置。一个更好的解决方案是只包含一个包含 jar 文件和数据库的文件夹。我以前见过这样做,但我自己不知道该怎么做
    • >我不想将数据库嵌入到 .jar 文件中
    • 我将如何指定类路径?我不确定你的意思。这是我在主课上的东西还是与 gradle 有关的东西?
    • 您通常如何运行您创建的程序?
    • 自从我下载了 Minecraft 之后,我就一直在命令行运行它们,而且双击有点困难。
    【解决方案2】:

    问题

    Gradle 所做的部分工作是依赖管理。这意味着它知道您需要哪些依赖项以及如何找到它们(基于构建脚本中的配置)。当您通过 Gradle 执行/构建应用程序时,该工具将自动搜索存储库、下载+缓存依赖项,并将这些依赖项放在类路径/模块路径中。部署 JAR 文件后,Gradle 将不再涉及,因此您的部署负责包含所需的依赖项。

    换句话说,您需要将应用程序的依赖项与应用程序 JAR 文件一起提供。


    解决方案

    您基本上只需要确保在您的应用程序中包含应用程序的依赖项。这里至少有三种方法可以做到这一点。

    复制依赖项

    作为构建过程的一部分,将依赖项复制到构建文件夹中。以下是此类任务的示例,使用 Kotlin DSL

    tasks {
        val jar by existing(Jar::class)
    
        val copyDependencies by registering(Copy::class) {
            from(configurations.runtimeClasspath)
            into(jar.get().destinationDirectory)
        }
    
        jar.configure {
            finalizedBy(copyDependencies)
        }
    }
    

    现在,如果您执行./gradlew jar,Gradle 将创建 JAR 文件,然后将依赖项复制到与 JAR 文件相同的目录中。然后你只需要确保所有的 JAR 文件都部署在一起。

    如果我没记错的话,默认的类路径是工作目录。但是要指定类路径,您将在执行应用程序时使用-cp-classpath--class-path。如果需要,可以使用-p--module-path 设置模块路径。

    胖罐子

    创建一个所谓的“胖”或“超级”JAR 文件。这是一个 JAR 文件,不仅包含您自己的应用程序代码,还包含您应用程序的所有依赖项。您可以为此配置jar 任务,但简单地应用Gradle Shadow Plugin 可能会更容易。

    // Kotlin DSL
    plugins {
        id("com.github.johnrengelman.shadow") version "<version>"
        // other plugins...
    }
    

    然后您将使用./gradlew shadowJar 创建胖 JAR。有关详细信息,请参阅用户指南。

    自包含应用程序

    使用jpackage 之类的工具创建一个独立的可执行文件。该工具为您提供了一个嵌入了所有代码和 JRE 的应用程序,然后为您提供了安装程序或本机可执行文件(例如 Windows 上的exe)。这是jpackageuser guide。 Gradle 插件可以让您更轻松地使用来自 Gradle 的 jpackage,例如 The Badass JLink Plugin

    注意jpackage 是在 Java 14 中添加的,并且一直孵化到 Java 16。还要注意 jpackage 不能“跨包”。也就是说,如果您在 Windows 上构建应用程序,那么您只能为 Windows 创建安装程序/可执行文件; MacOS 和 Linux 相同。如果您需要为多个平台打包,那么您需要访问每个平台。


    JavaFX

    由于您已使用 JavaFX 标记此问题,因此我想提醒您注意。虽然如果您没有使用 JavaFX 9+,那么这与您无关。

    从技术上讲,JavaFX 仅支持作为 命名 模块加载。这意味着它需要通过--module-path 或通过将其包含在jlink / jpackage 构建的自定义运行时映像中来放置在模块路径上。从 JavaFX 16 开始,如果从 未命名 模块(即类路径)加载 JavaFX,则会发出警告。

    可执行的 JAR 文件放置在类路径中。这包括胖 JAR。如果你没有使用包含 JavaFX 的 JDK——这意味着你有 Gradle 拉入 JavaFX 依赖项——那么 JavaFX 将被包含在你的胖 JAR 中并被放置在类路径中。现在,尽管不受支持并且现在发出警告,但如果 JavaFX 在类路径上,目前似乎没有任何问题。除了一个警告:您的主类不能是javafx.application.Application 的子类。您必须创建一个单独的主类来简单地启动 JavaFX。

    正因为如此,我强烈推荐使用jpackage 来部署JavaFX 应用程序。您可能还想阅读this Q&A

    【讨论】:

    • 谢谢,这在很多方面都非常有帮助。我肯定想使用概述的第一个解决方案:复制依赖项。不过,我不确定将什么放入我的 build.gradle 中。我复制了 Kotlin 部分并将 替换为缺少的类 org.apache.derby.jdbc.EmbeddedDriver。由于它现在没有构建,我相信我做错了。我应该改变什么?再次感谢!
    • 替换&lt;class&gt;在哪里?我的答案中没有任何内容。请注意我在您的 build.gradle.kts 文件中提供的 Kotlin DSL 示例。如果您有一个build.gradle 文件,那么您使用的是 Groovy DSL,因此您需要将 Kotlin 转换为 Groovy(旁注:Kotlin 和 Groovy 是两种可以在 JVM 上运行的不同编程语言,例如 Java) .不幸的是,我对 Groovy DSL 不太熟悉,所以我不确定它会是什么样子。
    • 我不是一个 gradle 人,但非常乐意帮助您(我猜是一个相当简单的)应用程序无需 3rd 方库/工具即可运行。我需要一个指向您文件的链接
    • @g00se 在 Gradle 中,使用第三方插件通常比尝试自己配置所有内容要简单得多。尤其是在使用成熟的插件时。并注意 OP 似乎想要使用的“复制依赖项”选项不使用第三方插件。虽然我仍然推荐jpackage(它本身不是第三方工具,它是 JDK 的一部分)。
    • 我明白了。实际上,我的最后一条评论可能会更好地移到问题的正下方,不是吗?
    猜你喜欢
    • 2017-06-15
    • 2019-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    相关资源
    最近更新 更多