头脑风暴:奇怪的JPA问题,可能是classpath或jar版本问题?

我看到一个奇怪的错误消息,我正在寻找一些关于问题可能是什么的想法。 我对使用JPA有点新意。

我有一个应用程序,我使用Spring的Entity Manager Factory(LocalContainerEntityManagerFactoryBean),EclipseLink作为我的ORM提供程序,连接到MySQL DB并使用Maven构建。 我不确定这些是否重要……

当我将此应用程序部署到Glassfish时,应用程序按预期工作。

问题是,我创建了一组独立的unit testing,以便在Glassfish之外运行,但这些测试无法正常工作。 我收到以下错误( 我已经编辑了一些类名

com.xyz.abc.services.persistence.entity.MyEntity cannot be cast to com.xyz.abc.services.persistence.entity.MyEntity 

该对象不能转换为相同类型的类? 怎么可能?

这是一段错误的代码片段

 Query q = entityManager.createNamedQuery("MyEntity.findAll"); List entityObjects = q.getResultList(); for (Object entityObject: entityObjects) { com.xyz.abc.services.persistence.entity.MyEntity entity = (com.xyz.abc.services.persistence.entity.MyEntity) entityObject; 

以前,我有这个代码产生相同的错误:

 CriteriaQuery cq = entityManager.getCriteriaBuilder().createQuery(); cq.select(cq.from(com.xyz.abc.services.persistence.entity.MyEntity.class)); List entityObjects = entityManager.createQuery(cq).getResultList(); for (Object entityObject: entityObjects) { com.xyz.abc.services.persistence.entity.MyEntity entity = (com.xyz.abc.services.persistence.entity.MyEntity) entityObject; 

此代码的问题与我部署到服务器的问题相同。

如果它有帮助,这是最里面的例外

 Caused by: java.lang.ClassCastException: com.xyz.abc.services.persistence.entity.MyEntity cannot be cast to com.xyz.abc.services.persistence.entity.MyEntity at com.xyz.abc.services.persistence.entity.factory.MyEntityFactory.createBeans(MyEntityFactory.java:47) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:115) ... 37 more 

我猜测我在Glassfish中使用的jar子与我在测试中使用的瓶子不同。 我已经看过我列为“提供”的所有jar子,我很确定它们都是来自Glassfish的jar子。

如果您之前看过这个奇怪的问题,或者有任何纠正它的想法,请告诉我。

这也可能是类加载问题。 由两个不同的类加载器加载的相同类定义被JVM视为不同的类。

您可以尝试这样来获取有关游戏中类加载器的信息:

 Query q = entityManager.createNamedQuery("MyEntity.findAll"); List entityObjects = q.getResultList(); ClassLoader loader1 = com.xyz.abc.services.persistence.entity.MyEntity.getClass().getClassLoader(); System.out.println("MyEntity's class loader is " + loader1); for (Object entityObject: entityObjects) { ClassLoader loader2 = entityObject.getClass().getClassLoader(); System.out.println("Class loader of entity " + entityObject + " is " + loader2); } 

您当然可以使用对首选日志记录框架的调用,而不是System.out.println

这是一系列文章,其中包含有关类加载的更多详细信息。

这显然会引起ClassLoader问题(可能是由于EclipseLink需要编织)。 你使用LoadTimeWeaver吗? 你有配置javaagent的东西吗? 是否在Maven下的命令行中出现问题? 在你的IDE? 请澄清。