Java, Hibernate java.lang.ClassCastException: org.hibernate.collection.PersistentSet cannot be cast to java.util.HashSet
Asked Answered
M

4

7

I have two tables, DVD and Contact.

A DVD can be rented to a contact and a contact can rent many DVD's.

The many to one link (dvd-->contact) works fine.

But the other way fails: (contact-->dvd)

This is the contact mapping:

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

Here is setter getter for Contact:

private Set<Dvd> dvds = new HashSet<Dvd>();

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

When I try to get the DVD rented from a contact with this:

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

I get an Exception:

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

What does the Exception mean and how do I fix it?

Edit: This solved my problem:

.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
Mordred answered 3/1, 2011 at 12:24 Comment(1)
Agree with Bozho's answer, curious to know why you want to convert it to a concrete class, - what was your need to do that?Boarish
A
20

You don't need to cast to HashSet. It is a Set, and it does not provide any additional methods. So just don't cast.

This is a general rule when working with collections - don't refer to them with their concrete classes (unless you really need to). Use List and Set, rather than ArrayList and HashSet

Alphabetical answered 3/1, 2011 at 12:33 Comment(1)
HashSet does provide extra methods than Set, an example is the clone() method. I've ran into this problem today and need to manually create my clone now...Beachhead
H
9

Don't try to cast the Set dds into HashSet. Hibernate uses its own implementation of the Set interface called PersistentSet which does not derive from HashSet and hence the casting throws a ClassCastException. Either use it through the Set interface, or create a new HashSet using its constructor (in which case your changes to the set will not be reflected in Hibernate automatically).

Set<Dvd> tt = dds;

OR

HashSet<Dvd> tt = new HashSet<Dvd>(dds);
Heliozoan answered 3/1, 2011 at 12:31 Comment(1)
This should be the correct answer as it addresses the lack of clone() pointed out in another comment.Chifforobe
O
2

I've come across this problem recently. I was able to eradicate the casting problem.

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

Then you can get the objects by casting the objects in List, say.

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

PS: It's freaking 2013.

Ochoa answered 20/6, 2013 at 3:0 Comment(0)
C
1

Abhinav Sarkar's answer is correct of course, but there is also a mistake in your modeling.

The relationship between DVD and Contact is Many-To-Many, not Many-To-One (otherwise each DVD would be unique to one single customer)

Cleodel answered 3/1, 2011 at 12:36 Comment(3)
NONO a dvd can only be rent by one and only one user!Mordred
@vinise One user at a given time, yes. But if it can only be rented by one user ever, then you misunderstood the concept of renting something.Cleodel
yes :) don't worry its a very very specific case a dvd can be rent by a user and when the user bring it back the field contact (on dvd's row) is set to null ans then can be rent by an other user :)Mordred

© 2022 - 2024 — McMap. All rights reserved.