11

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.

2 Answers 2

17

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; } // .... } 
Sign up to request clarification or add additional context in comments.

4 Comments

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: I understand your pain. Unfortunately, the compiler completes erases all traces of T. It is called type erasure: java.sun.com/docs/books/tutorial/java/generics/erasure.html
@AdamPaynter it's really hard to explain erasure to a newbie why can you use the <T> that you see right in front of you.
@Nishant: You're right. I was in the same situation when I was learning Java. It seemed like it should be there! A violation of the principle of least astonishment. :)
7

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

3 Comments

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.
I'm not sure I understand. Could you explain it in a little bit more detail? Are there any implications for web application development?
This works great when you subclass the generic class directly. If you have multiple levels of inheritance, you'll need to account for them in figureOutPersistentClass by using getSuperClass.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.