【问题标题】:How to statically weave JPA entities using EclipseLink when there is no persistence.xml as the entities are managed by Spring当没有persistence.xml时如何使用EclipseLink静态编织JPA实体,因为实体由Spring管理
【发布时间】:2019-08-05 06:58:28
【问题描述】:

我有一个基于 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

【问题讨论】:

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


    【解决方案1】:

    我阅读了现有的documentation

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

    用法:
    StaticWeave [选项] 源目标

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

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

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

    -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 构建中采用相同的方法。

    【讨论】:

      【解决方案2】:

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

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

      PersistenceProviderResolverHolderPersistenceProvider#createEntityManagerFactory(getPersistenceUnitName(), properties) 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 的可用性。

      【讨论】:

        猜你喜欢
        • 2023-03-30
        • 2011-06-27
        • 2015-04-13
        • 1970-01-01
        • 2013-06-01
        • 2015-06-22
        • 1970-01-01
        • 2017-05-24
        • 1970-01-01
        相关资源
        最近更新 更多