2009-04-29 6 views
11

Ho un hibernate dao parametrizzato che esegue operazioni di base di crude e quando parametrizzato è usato come delegato per eseguire operazioni di crudità di base per un dato dao.Classe derivante da T generico

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

Voglio essere in grado di ricavare classe da T in fase di esecuzione per creare criteri di query in Hibernate, in modo tale che:

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

so:

T.getClass() 

non esiste, ma esiste un modo per ricavare l'oggetto Class corretto da T al runtime?

Ho guardato generici e riflessi ma non ho trovato una soluzione adatta, forse mi manca qualcosa.

Grazie.

risposta

17

La classe può essere passata come argomento del costruttore.

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

Sì questa è una soluzione che ho. Preferirei poter derivare la classe da T se possibile, senza aggiungere la dipendenza di classe. – bowsie

+8

@bowsie: capisco il tuo dolore. Sfortunatamente, il compilatore completo cancella tutte le tracce di T. Si chiama erasure di tipo: http://java.sun.com/docs/books/tutorial/java/generics/erasure.html –

+0

Ah ok, grazie Adam. – bowsie

7

c'è il modo come capire class del tipo di argomento T utilizzando la riflessione:

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

Ecco il modo in cui 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(); 
    } 

} 

Suppongo che questo solo funziona quando la tua ConcreteEntityDao è una superclasse diretta di HibernateDao<ConcreteEntity,...>.

ho trovato qui: www.greggbolinger.com/blog/2008/04/17/1208457000000.html

+1

funziona solo nel metodo (posizione dello stack) che crea l'oggetto parametrizzato. Non funziona se si riceve l'oggetto parametrizzato da un altro metodo. –

+0

Non sono sicuro di aver capito. Potresti spiegarlo un po 'più in dettaglio? Ci sono implicazioni per lo sviluppo di applicazioni web? – rdk

+0

Funziona alla grande quando si sottoclasse direttamente la classe generica. Se si dispone di più livelli di ereditarietà, è necessario considerarli in 'figureOutPersistentClass' utilizzando' getSuperClass'. –