当没有persistence.xml时,如何使用EclipseLink静态编织JPA实体,因为这些实体是由Spring管理的

时间:2019-03-14 11:37:35

标签: spring spring-data-jpa eclipselink compile-time-weaving

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

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

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

我设置了以下步骤(请注意,这不是Kotlin DSL的常规做法):

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

2 个答案:

答案 0 :(得分:1)

我阅读了以下现有的documentation

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

  

用法:
   StaticWeave [选项]源目标

     

选项:
  -classpath    设置用户类路径,使用“;”作为Windows系统中的定界符,并且   在Unix系统中为“:”。

     

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

     

-loglevel       为eclipselink日志级别指定一个文字值(OFF,SEVERE,WARNING,INFO,CONFIG,FINE,FINER,FINEST)。默认值   值是OFF。

     

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

看完用法说明后,在我看来,该类需要persistence.xml才能生成静态编织源。

我还测试了eclipselink maven插件,该插件在没有persistence.xml的情况下也可以正常工作,因为它生成了persistence.xml 如果使用StaticWeave.class不在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);
    }

完整的源代码为here

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

答案 1 :(得分:0)

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

我稍后提到的代码示例在Spring中不适用于JPA,但在Weld中适用。我认为您问题的答案与EntityManager的创建方式以及创建EntityManager的PersistenceUnit管理的类有关。两者之间没有区别。与其将EntityManagerFactory用作CDI生产者,不如将其自动装配或使用老式的应用程序上下文进行注册。因此,我认为您的问题的答案来自以下官方消息来源

PersistenceProviderResolverHolder PersistenceProvider#createEntityManagerFactory(getPersistenceUnitName(),属性) properties 替代了persistence.xml,可以在其中注册SEPersistenceUnitInfo-Object。

要开始查看:PersistenceProviderResolverHolder 稍后:PersistenceProvider

或者您可以尝试了解我的代码(参见下文)是如何做到的。但是我必须承认,对不起,我对该软件的这一部分并不感到骄傲。

我使用这些类和对象来创建一个模块,该模块可以模拟服务器部署的JPA-WAR-File。 为此,它将扫描一些类并标识实体。 稍后在Testcode中,一个所谓的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的可用性。