英文:
No suitable driver found for jdbc:sqlite on app image
问题
我有一个连接到SQLite的JavaFX应用程序,使用以下代码:
```java
Connection connection = DriverManager.getConnection("jdbc:sqlite:data.sqlite");
我在我的pom文件中添加了SQLite驱动程序的依赖项:
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.32.3.2</version>
</dependency>
我可以使用Maven Goals javafx:compile
和 javafx:run
顺利运行应用程序,一切都按预期工作,应用程序可以无问题地查询数据库。data.sqlite
文件被创建在项目的根文件夹中(与 src/
和 pom.xml
同一文件夹)。
然而,当我尝试运行使用 jlink
构建的可执行文件时,我得到了线程标题中描述的错误。首先,我运行了Maven目标 javafx:jlink
。这会在 target/image/
中生成一些内容。我导航到 target/image/bin
并运行 ./java -m <name-of-my-module>/<group-id>.App
,这是我构建的文件的运行命令。然后我得到了:
No suitable driver found for jdbc:sqlite:data.sqlite
还有一个 NullPointerException
,因为数据库初始化例程尝试访问我的数据库连接。如何解决这个问题?提前感谢您的帮助。
编辑:似乎解决方案与在调用 DriverManager.getConnection()
之前添加 Class.forName()
语句有关。我尝试了以下操作:
Class.forName("org.sqlite.JDBC");
Connection connection = DriverManager.getConnection("jdbc:sqlite:data.sqlite");
通过这样做,现在应用程序可以运行了!但是,它仍然崩溃。我得到了 ClassNotFoundException: org.sqlite.JDBC
。有什么提示吗...?
<details>
<summary>英文:</summary>
I have a JavaFX app that connects to SQLite using
```java
Connection connection = DriverManager.getConnection("jdbc:sqlite:data.sqlite");
I have the dependency for SQLite driver on my pom file:
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.32.3.2</version>
</dependency>
I can run the App smoothly using Maven Goals javafx:compile
and javafx:run
, everything works as expected and the app has no trouble querying the db. The data.sqlite
file is created on the project's root folder (same folder as src/
and pom.xml
).
However, when I try to run an executable file built with jlink
, I get the error described on the thread's title. First, I ran maven goal javafx:jlink
. This generates some stuff at target/image/
. I navigated to target/image/bin
and ran ./java -m <name-of-my-module>/<group-id>.App
, which is the command for running the file I built. Then I get:
No suitable driver found for jdbc:sqlite:data.sqlite
And a NullPointerException
because of the database init routines that try to access my database connection. How can I fix this? Thanks in advance.
EDIT: It seems that the solution has something to do with adding a Class.forName()
statement before calling DriverManager.getConnection()
. I tried doing the following:
Class.forName("org.sqlite.JDBC");
Connection connection = DriverManager.getConnection("jdbc:sqlite:data.sqlite");
By doing that, now the app renders! However, it still crashes. I get ClassNotFoundException: org.sqlite.JDBC
. Any hints...?
答案1
得分: 3
这可能不会直接与jlink一起工作,因为据我所见,SQLite尚未模块化。我在这里描述了一种替代方法https://github.com/dlemmermann/JPackageScriptFX,它也在内部使用jlink,但只是为了创建一个专用的运行时。使用这种方法,连接SQLite可以正常工作。我知道这一点,因为我的应用程序也使用相同版本的SQLite驱动程序而没有问题。
英文:
I fear this will not work directly with jlink because as far as I have seen SQLite is not yet modularized. I have described an alternative approach here https://github.com/dlemmermann/JPackageScriptFX which also uses jlink internally but only to create a dedicated runtime. With this approach linking SQLite works. I know that because my own applications also use the exact same version of the SQLite driver without problems.
答案2
得分: 0
我通过使用Draque Thompson的Module Info Inject解决了这个问题。基本上,这个程序会为你的.jar
创建一个module-info.class
,让JLink将其视为一个模块。(如果解释不够清楚,我对Java的模块系统了解不深,抱歉)。
所以,我所做的基本上是:
- 克隆Module-Info-Inject并运行它。
- 选择所需的jar文件夹,然后点击"Inject"。
- 在生成的
module-info.class
文件上获取模块的名称。在我的情况下,它是sqlite.jdbc
。 - 将新模块添加到我的项目的
module-info.java
中。
生成的SQLite驱动程序的module-info.class
文件如下所示:
module sqlite.jdbc {
requires transitive java.logging;
requires transitive java.sql;
exports org.sqlite;
exports org.sqlite.core;
exports org.sqlite.date;
exports org.sqlite.javax;
exports org.sqlite.jdbc3;
exports org.sqlite.jdbc4;
exports org.sqlite.util;
provides java.sql.Driver with org.sqlite.JDBC;
}
在我的项目的module-info.java
中要求该模块:
module com.demo {
requires sqlite.jdbc;
/ * ... * /
exports pkg.app;
}
英文:
I was able to solve this by using Draque Thompson's Module Info Inject. Basically what the program does is creating a module-info.class
for your .jar
, letting JLink see it as a module. (Sorry if the explanation is lacking, I don't have deep knowledge of Java's module system).
So basically what I done was:
- Clone Module-Info-Inject and run it.
- Select the desired jar folder and click "Inject".
- On the generated
module-info.class
file, get the module's name. In my case it wassqlite.jdbc
. - Add the new module to my project's
module-info.java
.
The generated module-info.class
file for SQLite driver:
module sqlite.jdbc {
requires transitive java.logging;
requires transitive java.sql;
exports org.sqlite;
exports org.sqlite.core;
exports org.sqlite.date;
exports org.sqlite.javax;
exports org.sqlite.jdbc3;
exports org.sqlite.jdbc4;
exports org.sqlite.util;
provides java.sql.Driver with org.sqlite.JDBC;
}
Requiring the module in my project's module-info.java
:
module com.demo {
requires sqlite.jdbc;
/ * ... * /
exports pkg.app;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论