编辑:虽然给出了一个(好的)答案,但这只涵盖了我问题中相当不重要的部分。这个问题的主要部分仍然悬而未决。
我在云项目中使用 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
)。
当在 JUnit
和 spring-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
运行所有变体