嗨,在本文中,我将向您展示如何轻松地将Gradle的功能与Flyway和JOOQ结合起来。 最后,您将获得构建秘诀,可以在每次更新数据库时自动更新模型。
问题
在开发具有数据库访问权限的应用程序时,我们通常会遇到问题,我们需要采用代码来更改数据库模式,反之亦然。
当我们尝试不重复事情时,一个好主意是,我们可以从另一个中产生一个。 例如,生成数据库访问并从实际数据库模式转移对象。 由于数据库应该是架构数据的真实来源,因此该示例似乎是一个不错的选择。 但是稍后会详细介绍。
另一个挑战是,与数据库的连接以根据架构生成类。 在生成类开始之前即时生成模式,这是一个很有吸引力的想法。 这将使开发人员在重新生成访问类时无需确保具有数据库连接。 从某种意义上来说,这很方便,因为他可以轻松地在本地计算机上引导环境。
让我们看看如何应对这些要求/挑战。
工具
第二个挑战的解决方案可能是Flyway ,因为它是用于管理和执行许多关系数据库的模式升级的智能工具。 Flyway的开发周期(很短)描述如下:在SQL文件中定义架构更改,启动应用程序,flyway会负责。
不,我们只需要一个从模式数据到数据访问/传输对象的生成器。 我在这里发现JOOQ非常方便,因为它是一个库,通过强大的DSL提供了用于关系数据库访问的包装,其中SQL在代码中可见,而没有隐藏在某些OR映射器的后面。
JOOQ是我们需要的代码生成器,因此我们不必一遍又一遍地编写和更改令人讨厌的,有时是麻烦的代码。
现在,我们已经做出了技术/库的选择,让我们继续进行
Gradle整合
我将介绍新的Gradle任务generateJOOQ。 它将负责使用Flyway进行模式迁移/创建以及使用JOOQ进行代码生成,并且应在每次compileJava运行之前执行。
让我们从必要的配置和sourceSets开始。 类将被生成到生成的源集这需要下面的代码片断中构建文件可用:
configurations {
compile.extendsFrom generatedCompile
}
sourceSets {
generated
main {
compileClasspath += generated.output
}
}
现在,下一步是通过向我们的build.gradle的buildscript块添加必要的依赖关系,使Gradle同时了解Flyway和JOOQ。
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.jooq:jooq-codegen:3.6.1'
classpath 'com.h2database:h2:1.4.188'
classpath 'org.flywaydb:flyway-core:3.2.1'
}
}
为了这个示例选择了H2数据库,但是您可以使用可以与Flyway和JOOQ结合使用的任何数据库驱动程序。
现在我们必须提供JOOQ的配置,以便它可以将类生成到正确的文件夹和类路径中
def writer = new StringWriter()
new groovy.xml.MarkupBuilder(writer)
.configuration('xmlns': 'http://www.jooq.org/xsd/jooq-codegen-3.6.0.xsd') {
jdbc() {
driver('org.h2.Driver')
url("jdbc:h2:file:${project.projectDir}/build/generator/${project.name}")
user('sa')
password('')
}
generator() {
database() {
}
generate() {
}
target() {
packageName('com.coderskitchen.example')
directory('src/generated/java')
}
}
}
下一步,我们可以创建generateJOOQ任务:
import org.flywaydb.core.Flyway
task generateJOOQ() {
doLast {
def Flyway flyway = new Flyway();
flyway.setDataSource("jdbc:h2:file:${project.projectDir}/build/generator/${project.name}", "sa", null);
flyway.setLocations("filesystem:${project.projectDir}/src/main/resources/db/migration")
flyway.migrate();
org.jooq.util.GenerationTool.generate(
javax.xml.bind.JAXB.unmarshal(new StringReader(writer.toString()), org.jooq.util.jaxb.Configuration.class)
)
}
}
如您所见,迁移文件来自src / main / resources / db / migration 。 这样做的好处是,如果我们愿意/必须的话,可以在我们的应用程序中交付迁移SQL文件,以便我们可以在生产/登台环境中直接迁移数据库。 如果环境不受我们的控制,例如当应用程序在外部客户计算机上运行时,这将非常有用。
Gradle任务之间的依赖关系将为compileJava- > compileGeneratedJava- > generateJOOQ && clean :
compileGeneratedJava.dependsOn clean
compileGeneratedJava.dependsOn generateJOOQ
compileJava.dependsOn compileGeneratedJava
最后,我们必须将JOOQ依赖项添加到generateCompile配置的依赖项中,否则我们的项目将无法构建:
dependencies {
generatedCompile 'org.jooq:jooq:3.6.1',
'org.jooq:jooq-meta:3.6.1',
'org.jooq:jooq-codegen:3.6.1'
}
整个最小构建文件如下所示
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.jooq:jooq-codegen:3.6.1'
classpath 'com.h2database:h2:1.4.188'
classpath 'org.flywaydb:flyway-core:3.2.1'
}
}
import org.flywaydb.core.Flyway
group 'com.coderskitchen'
version '1.0.0'
apply plugin: 'java'
apply plugin: 'idea'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
configurations {
compile.extendsFrom generatedCompile
}
sourceSets {
generated
main {
compileClasspath += generated.output
}
}
dependencies {
generatedCompile 'org.jooq:jooq:3.6.1',
'org.jooq:jooq-meta:3.6.1',
'org.jooq:jooq-codegen:3.6.1'
testCompile group: 'junit', name: 'junit', version: '4.11'
}
def writer = new StringWriter()
new groovy.xml.MarkupBuilder(writer)
.configuration('xmlns': 'http://www.jooq.org/xsd/jooq-codegen-3.6.0.xsd') {
jdbc() {
driver('org.h2.Driver')
url("jdbc:h2:file:${project.projectDir}/build/generator/${project.name}")
user('sa')
password('')
}
generator() {
database() {
}
generate() {
}
target() {
packageName('com.coderskitchen.example')
directory('src/generated/java')
}
}
}
task generateJOOQ() {
doLast {
def Flyway flyway = new Flyway();
flyway.setDataSource("jdbc:h2:file:${project.projectDir}/build/generator/${project.name}", "sa", null);
flyway.setLocations("filesystem:${project.projectDir}/src/main/resources/db/migration")
flyway.migrate();
org.jooq.util.GenerationTool.generate(
javax.xml.bind.JAXB.unmarshal(new StringReader(writer.toString()), org.jooq.util.jaxb.Configuration.class)
)
}
}
compileGeneratedJava.dependsOn clean
compileGeneratedJava.dependsOn generateJOOQ
compileJava.dependsOn compileGeneratedJava
最后,我们一起尝试了所有东西。 一切? 从设置的角度来看,这是正确的,只是缺少一些示例。
运行示例
该示例是关于一个简单的帆船比赛日历的,该日历分两次迭代编写
- 第一个将仅包含比赛日期的表格以及有关该地点的所有信息
- 第二次迭代会将这种模式迁移到更规范的模式,该模式将地点与日期分开
我将示例发布在github( https://github.com/coders-kitchen/gradle-jooq-flyway-example )上,并且有两个与上述迭代匹配的标签。
再见,度过愉快的一周
翻译自: https://www.javacodegeeks.com/2016/04/combining-power-gradle-flyway-jooq-seamless-development-databases.html