使用 Groovy 和 GraalVM 操作 SQL 数据库
作者:Paul King
发布时间:2022-07-29 02:07PM
原生元数据
任何使用过 GraalVM 的人都知道,通常需要向原生编译器提供某些信息。某些类可以在构建时初始化,而另一些应该在运行时初始化。如果访问某些类型的资源,则必须向编译器提供有关这些资源的知识。应用程序中可能通过反射调用或涉及序列化的部分,可能被认为不可达,因此不会被编译器自动包含。
每个应用程序中使用的库都将有自己的类和资源集,这些类和资源通常需要由使用该库的任何人处理。原生元数据存储库在每个库的基础上保存此信息的共享副本。一旦有人填充了元数据,其他使用相同库的项目就可以自动获取该信息。我们将在稍后详细介绍元数据集成,但首先,让我们看看我们的数据库应用程序。
在 Groovy 中使用 SQL
应用程序创建并填充了一个名为 customer
的数据库,其中包含四个客户。然后打印出它们。
import groovy.sql.Sql
import groovy.transform.CompileStatic
@CompileStatic
class H2Demo {
static void main(args) {
Sql.withInstance('jdbc:h2:./data/test') { sql ->
sql.execute 'DROP TABLE IF EXISTS customers'
sql.execute 'CREATE TABLE customers(id INTEGER AUTO_INCREMENT, name VARCHAR)'
for (cust in ['Lord Archimonde', 'Arthur', 'Gilbert', 'Grug']) {
sql.executeInsert "INSERT INTO customers(name) VALUES $cust"
}
println sql.rows('SELECT * FROM customers').join('\n')
}
}
}
Groovy 的 Sql
类使此操作变得相对容易。withInstance
方法将创建数据库连接,并在完成后关闭连接。executeInsert
方法使用的是 Groovy 插值字符串 (GString),它在后台创建了一个准备好的语句。
配置我们的原生构建
以下是我们的构建文件
plugins {
id 'application'
id 'groovy'
id 'org.graalvm.buildtools.native'
}
application {
mainClass = 'H2Demo'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'com.h2database:h2:2.1.210'
implementation 'org.apache.groovy:groovy:4.0.4'
implementation 'org.apache.groovy:groovy-sql:4.0.4'
}
graalvmNative {
agent {
defaultMode = 'standard'
}
metadataRepository {
enabled = true
}
binaries {
main {
buildArgs.addAll(
// '-H:IncludeSBOM=cyclonedx',
'--report-unsupported-elements-at-runtime',
'--initialize-at-run-time=groovy.grape.GrapeIvy,org.h2.store.fs.niomem.FileNioMemData',
'--initialize-at-build-time',
'--no-fallback',
)
}
}
}
我们使用 graalvm 原生构建插件。我们定义了 Groovy 和 H2 的依赖项。我们还可以向原生编译器提供任何必要的参数。重要的是,我们启用了与元数据存储库的集成。
当我们运行构建时,它将自动为我们创建原生应用程序。
paulk@pop-os:/extra/projects/groovy-graalvm-h2$ ./gradlew clean nativeRun ... > Task :nativeCompile [native-image-plugin] Using executable path: /extra/devtools/graalvm-ce-java17-22.2.0/bin/native-image ========================================================================================== GraalVM Native Image: Generating 'H2Demo' (executable)... ========================================================================================== ... [1/7] Initializing... (5.3s @ 0.26GB) Version info: 'GraalVM 22.2.0 Java 17 CE' Java version info: '17.0.4+8-jvmci-22.2-b06' C compiler: gcc (linux, x86_64, 11.2.0) Garbage collector: Serial GC 1 user-specific feature(s) - com.oracle.svm.polyglot.groovy.GroovyIndyInterfaceFeature [2/7] Performing analysis... [************] (51.7s @ 1.82GB) 10,597 (90.60%) of 11,697 classes reachable 17,002 (64.13%) of 26,510 fields reachable 58,165 (63.45%) of 91,666 methods reachable 393 classes, 100 fields, and 2,057 methods registered for reflection 65 classes, 74 fields, and 55 methods registered for JNI access 4 native libraries: dl, pthread, rt, z [3/7] Building universe... (8.0s @ 4.02GB) [4/7] Parsing methods... [**] (4.8s @ 3.85GB) [5/7] Inlining methods... [***] (3.0s @ 1.72GB) [6/7] Compiling methods... [******] (38.0s @ 3.63GB) [7/7] Creating image... (5.9s @ 1.70GB) 26.65MB (46.64%) for code area: 38,890 compilation units 28.04MB (49.05%) for image heap: 359,812 objects and 66 resources 2.46MB ( 4.31%) for other data 57.15MB in total ------------------------------------------------------------------------------------------ Top 10 packages in code area: Top 10 object types in image heap: 1.48MB sun.security.ssl 5.85MB byte[] for code metadata 1.06MB java.util 2.82MB java.lang.String 979.43KB java.lang.invoke 2.78MB java.lang.Class 758.29KB org.apache.groovy.parser.antlr4 2.47MB byte[] for general heap data 723.92KB com.sun.crypto.provider 2.04MB byte[] for java.lang.String 588.57KB org.h2.table 910.68KB com.oracle.svm.core.hub.DynamicHubCompanion 582.06KB org.h2.command 764.95KB java.util.HashMap$Node 494.23KB org.codehaus.groovy.classgen 761.53KB java.lang.Object[] 476.03KB c.s.org.apache.xerces.internal.impl.xs.traversers 715.65KB byte[] for embedded resources 468.69KB java.lang 584.75KB java.util.HashMap$Node[] 18.87MB for 370 more packages 8.28MB for 2535 more object types ------------------------------------------------------------------------------------------ 3.9s (3.2% of total time) in 30 GCs | Peak RSS: 6.22GB | CPU load: 6.48 ------------------------------------------------------------------------------------------ Produced artifacts: /extra/projects/groovy-graalvm-h2/build/native/nativeCompile/H2Demo (executable) /extra/projects/groovy-graalvm-h2/build/native/nativeCompile/H2Demo.build_artifacts.txt (txt) =========================================================================================== Finished generating 'H2Demo' in 2m 1s. [native-image-plugin] Native Image written to: /extra/projects/groovy-graalvm-h2/build/native/nativeCompile > Task :nativeRun [ID:1, NAME:Lord Archimonde] [ID:2, NAME:Arthur] [ID:3, NAME:Gilbert] [ID:4, NAME:Grug]
检查原生镜像速度
我们还可以检查原生镜像构建后的速度
paulk@pop-os:/extra/projects/groovy-graalvm-h2$ time build/native/nativeCompile/H2Demo [ID:1, NAME:Lord Archimonde] [ID:2, NAME:Arthur] [ID:3, NAME:Gilbert] [ID:4, NAME:Grug] real 0m0.027s user 0m0.010s sys 0m0.011s
更多信息
查看存储库中的完整源代码
https://github.com/paulk-asert/groovy-graalvm-h2
结论
我们已经查看了一个简单的 H2 数据库应用程序以及使用 Groovy 和 GraalVM 创建原生应用程序所涉及的步骤。