在 运行 时间从头开始设置数据库

Setting up a database from scratch at run time

我目前正在开发一个 Java 数据库应用程序,我希望它是完全独立的(即单个 .jar 文件和一个配置文件,没有别的)。这是一个非常小的项目,我没有像商业代码库那样花哨的构建管道和额外的应用程序数据 - 因此需要一个简单的单 jar 解决方案。

实现这一点的部分工作涉及在应用程序中嵌入 H2 并在 运行 时设置数据库。但是,我不确定如何在这个用例中应用我想要的模式。让我们以这个table为例。

+-------------+------------+----------+---------+
| Column name | Data type  | Nullable | Default |
+-------------+------------+----------+---------+
| id          | BIGINT     | FALSE    | -       |
| prefix      | VARCHAR(3) | FALSE    | 'g!'    |
+-------------+------------+----------+---------+

到目前为止,这是我的两个解决方案。

使用 jOOQ 以编程方式布置 tables:

try (DSLContext ctx = DSL.using(dataSource, SQLDialect.MYSQL)) {
    ctx.createTableIfNotExists("guilds")
        .column("id", SQLDataType.BIGINT.nullable(false))
        .column("prefix", SQLDataType.VARCHAR(3).nullable(false).defaultValue("g!"))
        .constraint(constraint("PK_GUILDS").primaryKey(field("id")))
        .execute();
}

当然,在这个用例中,我不能使用 jOOQ 的代码生成,因为没有什么可以生成 classes。这行得通并且完全是程序化的,但它真的很难看并且用静态导入阻塞了 class 。扩展它以添加更多 tables and/or 列是痛苦的,并且使代码的可读性更差。

我尝试的另一件事是 Flyway,它非常简单而且没有那么可怕。我只需要一个小的 .sql 文件来设置我的架构,如下所示:

create table guilds(
    id BIGINT NOT NULL,
    prefix VARCHAR(3) NOT NULL,
    PRIMARY KEY(id)
);

然后我可以 运行 一个 Gradle 任务来生成一个空的 H2 数据库,其中所有 table 都已经设置好并准备就绪。 Gradle 甚至让我在构建之前将此任务指定为 运行。在这种情况下,我还可以使用 jOOQ 代码生成,这使得 lot 的事情变得更容易。不过,这一切都发生在编译时,据我所知,我必须用一个空的数据库文件打包应用程序。当然,这并不能满足我最初想要的单罐需求。

是否有一种干净的 "conventional" 方法来做到这一点,或者以这种方式构建应用程序只是在涉及数据库时不是任何人都会做的事情?

您应该使用 Spring–Data 并让它为您完成工作。在应用程序属性中,您设置数据源。您创建实体(注释 类)和存储库。一旦你完成并假装你正在使用休眠,你可以在你的应用程序属性中放置一个 属性 比如 "hibernate.hbm2ddl.auto", "create-drop" 。这将自动为您创建和删除数据库。不需要额外的代码。还有更多这样的配置选项。您会在手册中找到它们。

从 jOOQ 的角度来看,我们强烈建议您选择 Flyway approach 或类似的东西。这样做的原因是,当您的项目增长时,您会很高兴选择了一条您可以完全控制 架构演变的路径,而不是让第三方产品进行管理对你来说,jOOQ 集成毫不费力。

您之前尝试过的 jOOQ DDL API 当然也可以工作,例如当您将此 API 与 Flyway 或类似 programmatic schema evolution API. You can still produce a single jar as output even if you have multiple modules as input. For example, you could use the maven-assembly-plugin 的东西一起使用以生成此单个 jar 时。这个特定的构建约束不应成为您决定如何管理数据库模式的驱动因素。