views:

605

answers:

2

I have a parameterized hibernate dao that performs basic crud operations, and when parameterized is used as a delegate to fulfil basic crud operations for a given dao.

public class HibernateDao <T, ID extends Serializable> implements GenericDao<T, ID>

I want to be able to derive Class from T at runtime to create criteria queries in Hibernate, such that:

public T findByPrimaryKey(ID id) {
    return (T) HibernateUtil.getSession().load(T.getClass(), id);
}

I know:

T.getClass()

does not exist, but is there any way to derive the correct Class object from T at runtime?

I have looked at generics and reflection but have not come up with a suitable solution, perhaps I am missing something.

Thanks.

+12  A: 

You could have the Class passed as a constructor argument.

public class HibernateDao <T, ID extends Serializable> implements GenericDao<T, ID> {

    private final Class<? extends T> type;

    public HibernateDao(Class<? extends T> type) {
        this.type = type;
    }

    // ....

}
Adam Paynter
Yes this is one solution I have. I would prefer to be able to derive the class from T if possible, without adding the Class dependency.
bowsie
@bowsie: I understand your pain. Unfortunately, the compiler completes erases all traces of T. It is called type erasure: http://java.sun.com/docs/books/tutorial/java/generics/erasure.html
Adam Paynter
Ahh okay, thanks Adam.
bowsie
A: 

There is the way how to figure out class of type argument T using reflection:

private Class<T> persistentClass = (Class<T>)
    ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];

Here is the way how I use it:

public class GenericDaoJPA<T> implements GenericDao<T> {

    @PersistenceContext
    protected EntityManager entityManager;

    protected Class<T> persistentClass = figureOutPersistentClass();

    private Class<T> figureOutPersistentClass() {
        Class<T> clazz = (Class<T>)((ParameterizedType) (getClass().getGenericSuperclass())).getActualTypeArguments()[0];
        log.debug("persistentClass set to {}", clazz.getName());
        return clazz;
    }

    public List<T> findAll() {
        Query q = entityManager.createQuery("SELECT e FROM " + persistentClass.getSimpleName() + " e");
        return (List<T>) q.getResultList();
    }

}

I suppose this only works when your ConcreteEntityDao is a direct superclass of HibernateDao<ConcreteEntity,...>.

I've found it here: www.greggbolinger.com/blog/2008/04/17/1208457000000.html

rdk
this only works in method (stack location) that creates the parameterized object. It doesn't work if you receive the parameterized object from another method.
Ran Biron
I'm not sure I understand. Could you explain it in a little bit more detail? Are there any implications for web application development?
rdk