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

Posted

技术标签:

【中文标题】在运行时从头开始设置数据库【英文标题】:Setting up a database from scratch at run time 【发布时间】:2019-11-11 01:05:00 【问题描述】:

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

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

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

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

使用 jOOQ 以编程方式布局表格:

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 的代码生成,因为没有什么可以生成类。这可行并且完全是程序化的,但它真的很丑陋并且用静态导入阻塞了类。扩展它以添加更多表和/或列是痛苦的,并且使代码的可读性更差。

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

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

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

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

我绝对将 Spring 视为一种解决方案。这一切都发生在运行时吗? 是的,当您的 Spring 应用启动时,您可以看到神奇的发生;) 这适用于快速设置,但这种方法如何在数据库模式有效后帮助其发展?我会说这会导致更进一步的并发症...... 你可以禁用 create drop 然后【参考方案2】:

从 jOOQ 的角度来看,我们强烈建议您选择 Flyway approach 或类似的东西。这样做的原因是,当您的项目发展壮大时,您会很高兴选择了一条完全控制模式演变的路径,而不是让第三方产品为您管理它,并且 jOOQ 集成可以毫不费力地工作。

您之前尝试过的 jOOQ DDL API 当然也可以工作,例如当您将此 API 与 Flyway 或类似于 programmatic schema evolution API 的东西一起使用时。即使您有多个模块作为输入,您仍然可以生成单个 jar 作为输出。例如,您可以使用maven-assembly-plugin 来生成这个单一的jar。这个特定的构建约束不应成为您决定如何管理数据库架构的驱动因素。

【讨论】:

以上是关于在运行时从头开始设置数据库的主要内容,如果未能解决你的问题,请参考以下文章

从头开始构建数据湖

从头开始为 storybook 和 webpack 设置绝对导入

WebAssembly:从头开始重建堆栈

运行 Django 的 ./manage.py syncdb 时自动创建管理员用户

如何从头开始编一个拼音输入法?

Heroku调度程序不是每小时运行一次