JPA/EclipseLink:了解类加载器问题



编辑:虽然给出了一个(好的)答案,但这只涵盖了我问题中相当不重要的部分。这个问题的主要部分仍然悬而未决。

我在云项目中使用 EclipseLink (2.6.2)。该项目是一个打包为WAR文件并部署在Apache Tomcat 8上的Web应用程序。持久性上下文是使用 Java 代码设置的,其中我使用 entityManagerFactoryBean.setPackagesToScan(packagesToScan) 指定要使用的实体。此配置通常按预期工作,其中准确找到指定包中的实体类。

我现在无法理解何时使用哪个类加载器,尤其是在考虑 Tomcat、运行测试和使用不同的连接池实现时。

在 Apache Tomcat (包括 Tomcat 的连接池)上运行时,DataSource 实例是使用 spring-cloud-connector 插件 ( spring-cloud-spring-service-connector ) 创建的。在此设置中,只要我不按照下面所述更改类加载器,一切都按预期工作(否则我将面临实体类的ClassNotFoundException)。

当在 JUnitspring-test 的帮助下运行单元测试时,DataSource实例是使用内存数据库 H2(使用 spring-jdbc 中的EmbeddedDatabaseBuilder)创建的。在此设置中,我必须指定 JPA 以使用用于DataSource实例的类加载器(JPA 属性映射中的键eclipselink.classloader),否则我会得到"对象...不是已知的实体类型"。

在嵌入式 Apache Tomcat 8 中运行测试时,我没有看到任何指示正在使用的连接池的消息。在此设置中,我还必须将类加载器设置为单元测试。

如果我将commons-dbcp (2.1.1) 添加到我的项目中,并显式配置 spring-cloud-connector 插件使用它而不是 Tomcat 的连接池,我可以在不配置类加载器的情况下在 Tomcat 上运行应用程序,但它也适用于上述类加载器规范。

对于测试,与上述方案相比,commons-dbcp不会更改任何内容(因为未使用相应的配置)。

总结:

    Tomcat
  • (Tomcat CP):仅对 JPA 使用未修改的类加载器
  • 雄猫(DBCP):两种变体
  • 测试:仅使用 DataSource 的类加载器进行 JPA

您能否帮助我了解这里的差异,并提出适用于所有情况的简单解决方案?我假设DBCP和Spring使用与Tomcat(以及Tomcat的连接池)不同的类加载器。

如果您需要更多信息,我很乐意添加它。

编辑:我添加了一个示例项目,其中包含有关如何重现的大自述文件。

https://github.com/C-Otto/classloaderexample

"当我开始使用 mvn tomcat7:run 时,我收到另一个错误,使用 Tomcat 的 连接池 (云数据库配置) 并且不重新配置 classloder (JpaConfig):"

您必须在 maven 插件上配置 PostreSQL 依赖项。你得到的类未找到,因为PostgreSQL JAR不在路径中:

<plugin>
  <groupId>org.apache.tomcat.maven</groupId>
  <artifactId>tomcat7-maven-plugin</artifactId>
  <version>2.2</version>
  <configuration>
    <port>8080</port>
    <path>/</path>
  </configuration>
  <!-- For any extra dependencies needed when running embedded Tomcat (not WAR dependencies) add them below -->
  <dependencies>
    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>9.4-1206-jdbc41</version>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
</plugin>

也看看 https://tomcat.apache.org/maven-plugin-2.2/run-mojo-features.html

我忘了在(JpaConfigWithDatasourceClassloader.getJPAProperties)上包含类加载器更改:

properties.put(CLASSLOADER, new java.net.URLClassLoader(
   ((java.net.URLClassLoader)classLoader).getURLs(), JpaConfigWithDatasourceClassloader.class.getClassLoader()  ) 
) ;

有了这个,您可以使用tomcat7:run运行所有变体

最新更新