2009-04-29 9 views
11

J'ai un hibernate dao paramétré qui effectue des opérations élémentaires de crud, et qui, lorsqu'il est paramétré, est utilisé en tant que délégué pour accomplir les opérations de base de crud pour un dao donné.Dérivation d'une classe du générique T

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

Je veux être en mesure de tirer classe de T lors de l'exécution pour créer criteria dans Hibernate, tels que:

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

Je sais:

T.getClass() 

n'existe pas, mais existe-t-il un moyen de dériver l'objet Class correct de T à l'exécution? J'ai examiné les génériques et la réflexion, mais je n'ai pas trouvé de solution appropriée, peut-être qu'il me manque quelque chose.

Merci.

Répondre

17

La classe peut être transmise en tant qu'argument de constructeur.

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

Oui c'est une solution que j'ai. Je préférerais pouvoir dériver la classe de T si possible, sans ajouter la dépendance de classe. – bowsie

+8

@bowsie: Je comprends votre douleur. Malheureusement, le compilateur complète efface toutes les traces de T. On l'appelle effacement de type: http://java.sun.com/docs/books/tutorial/java/generics/erasure.html –

+0

Ahh d'accord, merci Adam. – bowsie

7

Il y a la façon comment comprendre class des arguments de type T utilisant la réflexion:

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

Voici la manière dont je l'utilise:

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

} 

Je suppose que cela ne Fonctionne lorsque votre ConcreteEntityDao est une superclasse directe de HibernateDao<ConcreteEntity,...>.

Je l'ai trouvé ici: www.greggbolinger.com/blog/2008/04/17/1208457000000.html

+1

cela ne fonctionne que dans la méthode (emplacement de la pile) qui crée l'objet paramétré. Cela ne fonctionne pas si vous recevez l'objet paramétré d'une autre méthode. –

+0

Je ne suis pas sûr de comprendre. Pourriez-vous l'expliquer un peu plus en détail? Y a-t-il des implications pour le développement d'applications Web? – rdk

+0

Cela fonctionne très bien lorsque vous sous-classez la classe générique directement. Si vous avez plusieurs niveaux d'héritage, vous devrez les prendre en compte dans 'figureOutPersistentClass' en utilisant' getSuperClass'. –

Questions connexes