在 Quarkus 中使用纯 Java 运行 SQLite
如果我们可以在纯 Java 中运行 C 语言数据库,零配置,甚至轻松将其编译为原生镜像,那会怎么样?有了新的 Quarkiverse 扩展 quarkus-jdbc-sqlite4j,您就可以做到这一点。
传统上,Java 中的嵌入式数据库需要重新实现其 C 语言对应版本,这通常会导致行为差异、优化缺失和错误修复延迟。然而,sqlite4j 提供了一个 JDBC 驱动程序,该驱动程序利用了原始 SQLite C 语言实现,同时安全地运行在一个沙箱环境中。
实践示例
要查看 quarkus-jdbc-sqlite4j 的实际应用,您可以从任何现有的 Quarkus 应用程序或 quickstarts 开始。如果您需要现成的示例,请查看 此演示仓库,它使用 Hibernate ORM 将 SQLite 集成到 Quarkus 应用程序中。
只需更改 JDBC 驱动程序的依赖项,您就可以在应用程序中嵌入功能齐全的 SQLite 数据库,同时保留原生 SQLite 实现的所有优势。
要开始,请将扩展依赖添加到您的 pom.xml 文件中
<dependency>
    <groupId>io.quarkiverse.jdbc</groupId>
    <artifactId>quarkus-jdbc-sqlite4j</artifactId>
</dependency>然后,使用标准的 JDBC 设置配置您的 Quarkus 应用程序以使用 SQLite
quarkus.datasource.db-kind=sqlite
quarkus.datasource.jdbc.url=jdbc:sqlite:sample.db
quarkus.datasource.jdbc.min-size=1您现在可以像往常一样使用 Hibernate 和 Panache 来使用您的数据源。请注意,我们将最小连接池大小保持 > 0,以避免将数据库从磁盘重复复制到内存中。
在安全沙箱中运行
在底层,SQLite 在完全内存中的沙箱环境中运行,确保安全性和隔离性。
 
当打开到本地文件的连接时,会发生以下情况:
- 
数据库文件从磁盘复制到内存中的虚拟文件系统。 
- 
建立到内存数据库的连接。 
虽然这种方法非常安全,但许多用户需要持久化数据库更改。一个推荐的解决方案是定期将内存数据库备份到磁盘。这可以通过一个计划任务来实现,该任务:
- 
将内存数据库备份到新文件中。 
- 
将备份文件复制到主机文件系统。 
- 
原子地用新备份替换旧数据库文件。 
这种设置确保了无缝的体验,同时保持了 SQLite 的沙箱安全性。您可以根据自己的具体需求调整此方法。
以下是一个示例实现
@ApplicationScoped
public class SQLiteBackup {
    @ConfigProperty(name = "quarkus.datasource.jdbc.url")
    String jdbcUrl;
    @Inject
    AgroalDataSource dataSource;
    // Execute a backup every 10 seconds
    @Scheduled(delay=10, delayUnit=TimeUnit.SECONDS, every="10s")
    void scheduled() { backup(); }
    // Execute a backup during shutdown
    public void onShutdown(@Observes ShutdownEvent event) { backup(); }
    void backup() {
        String dbFile = jdbcUrl.substring("jdbc:sqlite:".length());
        var originalDbFilePath = Paths.get(dbFile);
        var backupDbFilePath = originalDbFilePath
                                    .toAbsolutePath()
                                    .getParent()
                                    .resolve(originalDbFilePath.getFileName() + "_backup");
        try (var conn = dataSource.getConnection();
                var stmt = conn.createStatement()) {
            // Execute the backup
            stmt.executeUpdate("backup to " + backupDbFilePath);
            // Atomically replace the DB file with its backup
            Files.move(backupDbFilePath, originalDbFilePath,
                StandardCopyOption.ATOMIC_MOVE,
                StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException | SQLException e) {
            throw new RuntimeException("Failed to back up the database", e);
        }
    }
}技术深入探讨
sqlite4j 将官方 SQLite C 语言 amalgamation 编译为 WebAssembly (Wasm),然后使用 Chicory AOT 编译器将其转换为 Java 字节码。这使得 SQLite 可以在纯 Java 环境中运行,同时保持其全部功能。
 
结论
有了新的 quarkus-jdbc-sqlite4j 扩展,您可以兼顾两全其美:SQLite 的强大功能和可靠性,以及 Java 的安全性和可移植性。此扩展无缝地将 SQLite 集成到 Quarkus 应用程序中,同时保持轻量级和安全架构。最重要的是,所有这些都可以轻松地与 native-image 编译。
准备好尝试了吗?在您的项目中试用 quarkus-jdbc-sqlite4j,体验在 Quarkus 中使用纯 Java 运行 SQLite 的优势!