Can't use List <Object> return type HibernateTemplate.findByCriteria (criteria)
I am trying to get records using HibernateTemplate.findByCriteria (criteria).
It returns a List and I try to pass it to a List, but that doesn't allow me to do that. How to display a list to a list?
Here's my sample code:
public List<User> getUserList(String status, String type)
{
DetachedCriteria joinCriteria = DetachedCriteria.forClass(UserDetails.class)
.add(Restrictions.eq("status", status));
DetachedCriteria criteria = joinCriteria.createCriteria("user")
.add(Restrictions.eq("type", type));
return (List<User>) template.findByCriteria(criteria); // Gives error "Cannot cast from List<Object> to List<User>"
}
First of all, as you have already noticed, Java does not extend the subclass relationship to templates. This means that if you have two classes A
and B
, where B extends A
, then is C<B>
not a subclass C<A>
, which is exactly what the compiler is trying to tell you. the oracle documentation also talks about this. Despite being a "hack" related to laurentiu-l, you can consider this alternative solution, which in my opinion is a little less "hackish":
final List<User> returnValue = new LinkedList<>();
for(Object user : template.findByCriteria(criteria)) {
returnValue.add((User)user);
}
return returnValue;
A little bit about why Java doesn't extend subclasses to generics. Let's assume he did and consider the following three classes:
class Animal { }
class Dog extends Animal { }
class Cat extends Animal { }
Now let's write the following code:
List<Dog> dogList = new LinkedList<>();
// Perfectly fine, since Dog extends Animal
List<Animal> animalList = dogList;
// Fine again, since a Cat is an Animal, so we can put it in the list
animalList.add(new Cat());
// Oops...
Dog dog = dogList.get(0);
This code will compile fine but throw a runtime error. To avoid such complications, Java has completely banned this generic subtyping extension entirely.