从列表到单个对象的 ClassCastException 错误

ClassCastException Error from List to Single Object

我在从列表中获取单个位置对象时遇到问题。 在 primefaces dataTable 中调用 getLocations() 有效。我可以显示所有位置。 但是当我想从位置列表中获取单个位置时,我总是得到一个 ClassCastException。 我使用 JPA (Hibernate)。

实体 Bean:

@Entity
@Table(name = "location")
@NamedQueries({
    @NamedQuery(name = "Location.findAll", query = "SELECT l FROM Location l")})
public class Location implements Serializable {
    private static final long serialVersionUID = 1L;

@Column(name = "name")
private String name;
...

CDI 豆:

private List<Location> locations = null;

@PostConstruct
public void init() {
    locations = getService().findAll();
    Iterator iter = getLocations().iterator();
    Location first = (Location)iter.next(); //ClassCastException

同样的问题:

for (Location location : getLocations()) //Classcastexception
 {...}

错误信息:

java.lang.ClassCastException: package.ejb.entity.Location cannot be cast to package.ejb.entity.Location

更新: 整个应用程序是一个 EAR 项目。 Location Entity Bean 包含在 EJB-Jar 中。 还有 LocationService Session Bean,它被注入到 CDI Bean 中。 (对于 findAll() 调用)

CDI Bean 包含在 WAR。

@shruti1810 提到,可能存在 class 加载问题。 我阅读了来自 Oracle 的文档 The Class Loader Hierarchy 我所了解的是,EJB class 加载器是 WAR class 加载器的父级。因此我不明白为什么会有 ClassCastException。 CDI Bean 中的位置是否是从另一个 Class 加载器加载的,而不是 findAll() 方法给出的位置?

这似乎是一个 class 加载程序问题 - 当两个不同的 class 加载相同的 class 时,相同的 class 上的 ClassCastException 是可能的loaders,即你已经用一个 classloader 加载了 class,然后尝试将它转换为由另一个 classloader 加载的相同 class。

在这里,您可以做以下两件事之一:

有一个通用的 classloader,它加载 classes 以供您的自定义 classloader 使用。因此,在您的情况下,您将拥有一个新的 classloader,它将加载给定的 class,而您的自定义 classloader 将扩展此 classloader。

另一种解决方案是在两个 class 加载器之间传递 "serialized" 状态。将一个实例序列化为字节数组,并通过反序列化对象流在另一个 classloader 中重建对象。

通过将我的休眠版本从 4.3.9-Final 降级到 4.3.5-Final 来修复它。我还不知道是什么原因导致了这个问题。但是似乎hibernate 4.3.5+有几个问题。

另一个主题,具有类似的修复: here