7

我有一个基于 Spring 的项目,因此实体管理器是通过编程方式设置的,不需要persistence.xml 文件来列出所有实体。

我目前正在使用加载时间编织,但正在尝试使用 Eclipselink 和 Gradle 进行静态编织。我想复制 maven eclipselink 插件执行的操作:

https://github.com/ethlo/eclipselink-maven-plugin

我设置了以下 gradle(请注意,它是 Kotlin DSL 而不是 groovy):

task<JavaExec>("performJPAWeaving") {


    val compileJava: JavaCompile = tasks.getByName("compileJava") as JavaCompile
    dependsOn(compileJava)

    val destinationDir = compileJava.destinationDir

    println("Statically weaving classes in $destinationDir")
    inputs.dir(destinationDir)
    outputs.dir(destinationDir)
    main = "org.eclipse.persistence.tools.weaving.jpa.StaticWeave"
    args = listOf("-persistenceinfo", "src/main/resources", destinationDir.getAbsolutePath(), destinationDir.getAbsolutePath())

    classpath = configurations.getByName("compile")


}

当我尝试运行该任务时,编织任务失败,因为它正在寻找一个不存在的 persistence.xml。

有什么方法可以在基于 Spring 的 JPA 项目中静态编织 JPA 实体?

Exception Description: An exception was thrown while processing persistence.xml from URL: file:/home/blabla/trunk/my-module/src/main/resources/
Internal Exception: java.net.MalformedURLException
        at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionProcessingPersistenceXML(PersistenceUnitLoadingException.java:117)
        at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processPersistenceXML(PersistenceUnitProcessor.java:579)
        at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processPersistenceArchive(PersistenceUnitProcessor.java:536)
        ... 6 more
Caused by: java.net.MalformedURLException
        at java.net.URL.<init>(URL.java:627)
        at java.net.URL.<init>(URL.java:490)
        at java.net.URL.<init>(URL.java:439)
        at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:620)
        at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:148)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:806)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:771)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
        at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processPersistenceXML(PersistenceUnitProcessor.java:577)
        ... 7 more
Caused by: java.lang.NullPointerException
        at java.net.URL.<init>(URL.java:532)
        ... 17 more
4

2 回答 2

2

我阅读了以下现有文档

org.eclipse.persistence.tools.weaving.jpa.StaticWeave

用法:
StaticWeave [options] 源目标

选项:
-classpath 设置用户类路径,使用“;” 在 Window 系统中作为分隔符,在 Unix 系统中作为“:”。

-log 日志文件的路径,默认为标准输出。

-loglevel 指定 eclipselink 日志级别的文字值(OFF、SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST)。默认值为关闭。

-persistenceinfo 路径包含 META-INF/persistence.xml。仅当源不包含它时才需要。类路径必须包含执行编织所需的所有类。

查看使用说明后,在我看来这个类需要persistence.xml生成静态编织源。

我还测试了 eclipselink maven 插件,它在没有persistence.xml你指出的情况下工作,因为它persistence.xml 在调用StaticWeave.classif It is not located in之前生成CLASSPATH,使用这种方法。

 private void processPersistenceXml(ClassLoader classLoader, Set<String> entityClasses)
    {
        final File targetFile = new File(this.persistenceInfoLocation + "/META-INF/persistence.xml");
        getLog().info("persistence.xml location: " + targetFile);

        final String name = project.getArtifactId();
        final Document doc = targetFile.exists() ? PersistenceXmlHelper.parseXml(targetFile) : PersistenceXmlHelper.createXml(name);

        checkExisting(targetFile, classLoader, doc, entityClasses);

        PersistenceXmlHelper.appendClasses(doc, entityClasses);
        PersistenceXmlHelper.outputXml(doc, targetFile);
    }

完整的源代码在这里

我认为您可以在gradle构建中采用相同的方法。

于 2019-07-25T07:55:06.383 回答
0

我承认,我不完全理解你所说的编织是什么意思。如果您需要动态创建提供 JPA-Entitymanagers 的 PersistenceUnits,并且这些单元应该能够创建 Db-Schema(例如在 H2 中)并根据您在运行时提供的类动态管理实体,我的回答可能会有所帮助。

我稍后提到的代码示例不适用于 Spring 中的 JPA,但在 Weld 中。我认为您的问题的答案与如何创建 EntityManager 以及创建 EntityManager 的 PersistenceUnit 管理哪些类有关。这两者之间没有区别。除了将 EntityManagerFactory 用作 CDI-Producer 之外,您还可以自动装配它或使用老式的应用程序上下文注册它。因此,我认为您的问题的答案在于以下官方资料

PersistenceProviderResolverHolderPersistenceProvider#createEntityManagerFactory(getPersistenceUnitName(), properties) 属性是 persistence.xml 的替代品,可以在其中注册 SEPersistenceUnitInfo-Object。

开始看:PersistenceProviderResolverHolder 稍后:PersistenceProvider

或者您可以尝试了解我的代码(见下文)是如何做到的。但我不得不承认,我对那个软件的这一部分不是很自豪,对不起。

我使用这些类和对象来创建一个模块,该模块可以模拟服务器部署的 JPA-WAR-File。为此,它会扫描一些类并识别实体。稍后在测试代码中,一个所谓的 PersistenceFactory 创建 EntityManager 和 Datasources。如果使用 eclipselink,这个工厂会将这些类编织在一起。你不需要persistence.xml。在那里工作可能有助于回答您的问题。

如果看: ioc-unit-ejb:TestPersistencefactory 搜索创建的SEPersistenceUnitInfo。该接口由它返回的类列表提供

@Override
public List<String> getManagedClassNames() {
    return TestPersistenceFactory.this.getManagedClassNames();
}

此对象用于在 PersistenceProvider 的帮助下创建 Persistencefactory。只要类路径中提供了eclipselink,就可以发现这一点。

该代码不容易理解,因为它允许将 Hibernate 或 Eclipselink 用于 JPA,这取决于类路径中 jar 的可用性。

于 2019-07-24T21:05:57.220 回答