Java,Hibernate java.lang.ClassCastException: org.hibernate.collection.PersistentSet无法转换为java.util.HashSet

7

我有两个表,DVD和联系人。

DVD可以借给联系人,一个联系人可以借多个DVD。

一对多的关联(dvd->contact)可以正常工作。

但是另一种方式失败了:(contact->dvd)

这是联系人映射:

<set name="dvds" inverse="true">
   <key column="contactId"/>
   <one-to-many class="Dvd"/>
</set>

这里是联系人的setter getter方法:
private Set<Dvd> dvds = new HashSet<Dvd>();

public Set<Dvd> getDvds(){
   return dvds;
}
public void setDvds(Set<Dvd> dvds){
   this.dvds=dvds;
}

当我尝试从联系人处租赁DVD时:

HashSet<Dvd> tt = (HashSet<Dvd>)dds;

我遇到了一个异常:

java.lang.ClassCastException: org.hibernate.collection.PersistentSet 
cannot be cast to java.util.HashSet

这个异常是什么意思,我该怎么解决?

编辑:这个方法解决了我的问题:

.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)

同意Bozho的答案,很好奇你为什么想要将它转换为一个具体类 - 你有什么需要这样做的原因? - Anand Rockzz
4个回答

20

不需要将其强制转换为 HashSet,它是一个 Set,不提供任何附加方法。所以不要进行强制转换。

在使用集合时,这是一个通用规则 - 不要使用具体类来引用它们(除非你真的需要)。使用 ListSet,而不是 ArrayListHashSet.


1
HashSet 提供了比 Set 更多的方法,例如 clone() 方法。我今天遇到了这个问题,现在需要手动创建我的克隆... - Draken

9
不要尝试将dds Set强制转换为HashSet。Hibernate使用自己的Set接口实现,称为PersistentSet,它不是从HashSet派生的,因此转换会抛出ClassCastException。 要么通过Set接口使用它,要么使用其构造函数创建一个新的HashSet(在这种情况下,您对集合所做的更改不会自动反映在Hibernate中)。
Set<Dvd> tt = dds;

或者

HashSet<Dvd> tt = new HashSet<Dvd>(dds);

1
这应该是正确的答案,因为它解决了另一个评论中指出的缺少clone()的问题。 - Serge

2

我最近遇到了这个问题。

我能够消除强制转换的问题。

然后,您可以通过对列表中的对象进行强制转换来获取对象。

List<Object> listObject = Arrays.asList(ListFromHibernate.toArray());

MyObject x = (MyObject) listObject.get(1);

PS:现在已经是2013年了。


1

Abhinav Sarkar的回答是正确的,但你的建模还存在一个错误。

DVD和Contact之间的关系是多对多,而不是多对一(否则每个DVD将只适用于一个单独的客户)


一个 DVD 只能被一个用户租借! - gaymer
@vinise 一次只能被一个用户租用,是的。但如果它只能被一个用户永久租用,那么你就误解了“租用”这个概念。 - Sean Patrick Floyd
一张DVD可以被用户租借,当用户归还时,DVD行上的联系字段将设置为null,然后可以被其他用户租借 :) - gaymer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接