2009-04-29 17 views
11

Tengo un hibernate dao parametrizado que realiza operaciones crud básicas, y cuando se parametriza se utiliza como un delegado para cumplir las operaciones crud básicas para un dao dado.Derivación de clases desde genérico T

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

Quiero ser capaz de derivar la clase de T en tiempo de ejecución para crear consultas de criterios en hibernación, tal que:

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

sé:

T.getClass() 

no existe, pero, ¿hay alguna forma de derivar el objeto Class correcto de T en el tiempo de ejecución?

He examinado los genéricos y la reflexión, pero no he encontrado una solución adecuada, quizás me falta algo.

Gracias.

Respuesta

17

Puede pasar la clase como un argumento de constructor.

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; 
    } 

    // .... 

} 
+0

Si esta es una solución que tengo. Preferiría poder derivar la clase de T si es posible, sin agregar la dependencia de Clase. – bowsie

+8

@bowsie: entiendo tu dolor. Desafortunadamente, el compilador completa borra todos los rastros de T. Se llama borrado de tipo: http://java.sun.com/docs/books/tutorial/java/generics/erasure.html –

+0

Ahh bien, gracias Adam. – bowsie

7

No es la forma en cómo averiguar class del argumento de tipo T utilizando la reflexión:

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

Aquí es la manera cómo lo uso:

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(); 
    } 

} 

supongo que esto sólo funciona cuando su ConcreteEntityDao es una superclase directa de HibernateDao<ConcreteEntity,...>.

lo he encontrado aquí: www.greggbolinger.com/blog/2008/04/17/1208457000000.html

+1

esto solo funciona en el método (ubicación de la pila) que crea el objeto parametrizado. No funciona si recibe el objeto parametrizado de otro método. –

+0

No estoy seguro de entender. ¿Podrías explicarlo con un poco más de detalle? ¿Hay alguna implicación para el desarrollo de aplicaciones web? – rdk

+0

Esto funciona muy bien cuando subclases la clase genérica directamente. Si tiene múltiples niveles de herencia, deberá contabilizarlos en 'figureOutPersistentClass' utilizando' getSuperClass'. –

Cuestiones relacionadas