SBT如何使用DataNucleus从模型类生成元模型类? [英] How can SBT generate metamodel classes from model classes using DataNucleus?
问题描述
如何从持久性模型类(例如Client,Product,Invoice)生成元模型类(例如QClient,QProduct,QInvoice),以便可以使用JDOQL类型安全查询?
特别是,我对生成元模型类感兴趣,并且还对持久性类(通过SBT以及结合使用带有JDO注释的DataNucleus)运行字节码增强感兴趣.
这个问题与
有关
如何从SBT运行DataNucleus字节码增强器?
build.sbt
中定义执行元模型生成和字节码增强的功能,如下所示:def generateQueryEntities(sourcepath: File,
sources: Seq[File],
generated: File,
classes: File,
classpath: Seq[File],
javacOptions: Seq[String]): Seq[File] = {
IO.createDirectory(generated)
javaRunner(
javaTool = Option("javac"),
args =
javacOptions ++
(if(debug) Seq("-verbose") else Seq.empty[String]) ++
Seq(
"-sourcepath", sourcepath.absolutePath,
"-s", generated.absolutePath,
"-d", classes.absolutePath) ++
sources.map(p => p.absolutePath),
classpath = Option(classpath),
cwd = Option(classes)
)
classes.listFiles.filter(f => f.isFile && (f.ext == "class"))
}
def enhanceSchema(classes: File, classpath: Seq[File]): Seq[File] = {
javaRunner(
mainClass = Option("javax.jdo.Enhancer"),
args =
(if(debug) Seq("-v") else Seq.empty[String]) ++
Seq(
"-pu", "code-generation",
"-d", classes.absolutePath),
classpath = Option(classpath),
cwd = Option(classes)
)
classes.listFiles.filter(f => f.isFile && (f.ext == "class"))
}
下一步是为这些功能定义自定义任务.我们只需要如下所示的genjdoql
,因为字节码增强功能可以通过子任务manipulateBytecode
进行连线.请注意,需要SBT 0.13.8
或更高版本.
val genjdoql = TaskKey[Seq[File]]("genjdoql", "DataNucleus JDOQL Entities")
然后,您需要将这些功能连接到项目或模块的构建中,如下所示:
lazy val model =
project.in(file("model"))
.settings(publishSettings:_*)
.settings(librarySettings:_*)
.settings(paranoidOptions:_*)
.settings(otestFramework: _*)
.settings(deps_resolvers:_*)
//XXX .settings(deps_langtools:_*)
.settings(deps_tagging:_*)
.settings(deps_stream:_*)
.settings(deps_database:_*)
.settings(managedSources:_*)
.settings(
Seq(
// generate JDOQL Entities
genjdoql in Compile := {
generateQueryEntities(
sourcepath = (javaSource in Compile).value,
sources = (unmanagedSources in Compile).value,
generated = baseDirectory.value / "target" / scalav(scalaVersion.value) / "src_managed" / "main" / "java",
classes = (classDirectory in Compile).value,
classpath = (managedClasspath in Compile).value.files,
javacOptions = javacOpts :+ "-AqueryMode=PROPERTY"
)},
sourceGenerators in Compile <+= genjdoql in Compile,
// prevent javac from running annotation processors
javacOptions ++= Seq( "-proc:none" ),
// perform bytecode enhancement
manipulateBytecode in Compile := {
val previous = (manipulateBytecode in Compile).value
enhanceSchema(
classes = (classDirectory in Compile).value,
classpath =
(managedClasspath in Compile).value.files ++
(unmanagedResourceDirectories in Compile).value :+
(classDirectory in Compile).value)
previous
}
):_*)
.dependsOn(util)
有关完整示例,请查看
https://github.com/frgomes/poc-scala-datanucleus
How can I generate metamodel classes (like QClient, QProduct, QInvoice) from a persistence model classes (like Client, Product, Invoice) so that a JDOQL typesafe queries can be employed?
In particular, I'm interested on generating the metamodel classes and also run bytecode enhancement on persistence classes, via SBT and using DataNucleus with JDO annotations.
This question is related to
How can I run DataNucleus Bytecode Enhancer from SBT?
In a nutshell, you need to define functions in your build.sbt
which perform the generation of the metamodel and bytecode enhancement, like shown below:
def generateQueryEntities(sourcepath: File,
sources: Seq[File],
generated: File,
classes: File,
classpath: Seq[File],
javacOptions: Seq[String]): Seq[File] = {
IO.createDirectory(generated)
javaRunner(
javaTool = Option("javac"),
args =
javacOptions ++
(if(debug) Seq("-verbose") else Seq.empty[String]) ++
Seq(
"-sourcepath", sourcepath.absolutePath,
"-s", generated.absolutePath,
"-d", classes.absolutePath) ++
sources.map(p => p.absolutePath),
classpath = Option(classpath),
cwd = Option(classes)
)
classes.listFiles.filter(f => f.isFile && (f.ext == "class"))
}
def enhanceSchema(classes: File, classpath: Seq[File]): Seq[File] = {
javaRunner(
mainClass = Option("javax.jdo.Enhancer"),
args =
(if(debug) Seq("-v") else Seq.empty[String]) ++
Seq(
"-pu", "code-generation",
"-d", classes.absolutePath),
classpath = Option(classpath),
cwd = Option(classes)
)
classes.listFiles.filter(f => f.isFile && (f.ext == "class"))
}
The next step consists on defining custom tasks for these functions. We need only genjdoql
as shown below since the bytecode enhancement can be wired via sub-task manipulateBytecode
. Notice that SBT 0.13.8
or greater is required.
val genjdoql = TaskKey[Seq[File]]("genjdoql", "DataNucleus JDOQL Entities")
Then you need to wire these functions in the build of your project or module, like shown below:
lazy val model =
project.in(file("model"))
.settings(publishSettings:_*)
.settings(librarySettings:_*)
.settings(paranoidOptions:_*)
.settings(otestFramework: _*)
.settings(deps_resolvers:_*)
//XXX .settings(deps_langtools:_*)
.settings(deps_tagging:_*)
.settings(deps_stream:_*)
.settings(deps_database:_*)
.settings(managedSources:_*)
.settings(
Seq(
// generate JDOQL Entities
genjdoql in Compile := {
generateQueryEntities(
sourcepath = (javaSource in Compile).value,
sources = (unmanagedSources in Compile).value,
generated = baseDirectory.value / "target" / scalav(scalaVersion.value) / "src_managed" / "main" / "java",
classes = (classDirectory in Compile).value,
classpath = (managedClasspath in Compile).value.files,
javacOptions = javacOpts :+ "-AqueryMode=PROPERTY"
)},
sourceGenerators in Compile <+= genjdoql in Compile,
// prevent javac from running annotation processors
javacOptions ++= Seq( "-proc:none" ),
// perform bytecode enhancement
manipulateBytecode in Compile := {
val previous = (manipulateBytecode in Compile).value
enhanceSchema(
classes = (classDirectory in Compile).value,
classpath =
(managedClasspath in Compile).value.files ++
(unmanagedResourceDirectories in Compile).value :+
(classDirectory in Compile).value)
previous
}
):_*)
.dependsOn(util)
For a complete example, please have a look at
https://github.com/frgomes/poc-scala-datanucleus
这篇关于SBT如何使用DataNucleus从模型类生成元模型类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!