2010-08-26 18 views
0

J'essaie d'implémenter un DAO générique en utilisant les sessions contextuelles Hibernates. Voici mon coup de feu: |Comment créer une classe DAO générique à l'aide de sessions Hibernate Context

import java.io.Serializable; 

public interface GenericDao<T, ID extends Serializable> { 

/** Persist the newInstance object into database */ 
ID create(T newInstance); 

/** 
    * Retrieve an object that was previously persisted to the database using 
    * the indicated id as primary key 
    */ 
T read(ID primaryKey); 

/** Save changes made to a persistent object. */ 
void update(T transientObject); 

/** Remove an object from persistent storage in the database */ 
void delete(T persistentObject); 
} 


import java.io.Serializable; 

import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.Transaction; 
import org.springframework.transaction.annotation.Transactional; 

@Transactional 
@SuppressWarnings("unchecked") 
public class GenericDaoImpl<T, ID extends Serializable> implements 
    GenericDao<T, ID> { 
private SessionFactory sessionFactory; 

public void setSessionFactory(final SessionFactory sessionFactory) { 
    this.sessionFactory = sessionFactory; 
} 

@Override 
public ID create(final T newInstance) { 
    ID id = null; 
    final Session session = sessionFactory.openSession(); 
    final Transaction tx = session.beginTransaction(); 
    try { 
    id = (ID) session.save(newInstance); 
    tx.commit(); 
    session.close(); 
    } catch (final Exception e) { 
    if (tx != null) { 
    tx.rollback(); 
    } 
    e.printStackTrace(); 
    } finally { 
    if (session.isOpen()) { 
    session.close(); 
    } 
    } 
    return id; 
} 

@Override 
public T read(final ID primaryKey) { 
    T id = null; 
    final Session session = sessionFactory.openSession(); 
    final Transaction tx = session.beginTransaction(); 
    try { 
    id = (T) session.get(T, primaryKey); 
    tx.commit(); 
    session.close(); 
    } catch (final Exception e) { 
    if (tx != null) { 
    tx.rollback(); 
    } 
    e.printStackTrace(); 
    } finally { 
    if (session.isOpen()) { 
    session.close(); 
    } 
    } 
    return id; 
} 

@Override 
public void update(final T transientObject) { 
    final Session session = sessionFactory.openSession(); 
    final Transaction tx = session.beginTransaction(); 
    try { 
    session.saveOrUpdate(transientObject); 
    tx.commit(); 
    session.close(); 
    } catch (final Exception e) { 
    if (tx != null) { 
    tx.rollback(); 
    } 
    e.printStackTrace(); 
    } finally { 
    if (session.isOpen()) { 
    session.close(); 
    } 
    } 
} 

@Override 
public void delete(final T persistentObject) { 
    final Session session = sessionFactory.openSession(); 
    final Transaction tx = session.beginTransaction(); 
    try { 
    session.delete(persistentObject); 
    tx.commit(); 
    session.close(); 
    } catch (final Exception e) { 
    if (tx != null) { 
    tx.rollback(); 
    } 
    e.printStackTrace(); 
    } finally { 
    if (session.isOpen()) { 
    session.close(); 
    } 
    } 
} 
} 

applicationContext:

<bean id="domainDao" class="com.foo.dao.DomainDao"> 
    <property name="sessionFactory"> 
    <ref bean="sessionFactory"></ref> 
    </property> 

</bean> 

<bean id="domainDao2" class="com.foo.dao.GenericDaoImpl"> 
    <property name="sessionFactory"> 
    <ref bean="sessionFactory"></ref> 
    </property> 

</bean> 
<tx:annotation-driven transaction-manager="txManager" /> 


<bean id="txManager" 
    class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

La nôtre est une nouvelle application que nous essayons de mettre en œuvre avec Spring et Hibernate 3.0.3 3.5.5.

Q1. Bien que je l'ai mis en œuvre et fonctionne, ai-je fait de la bonne façon?

Q2. Comment puis-je implémenter l'opération find() en utilisant des génériques?

id = (T) session.get(T, primaryKey); 

Cette ligne génère une erreur de compilation.

MISE À JOUR: L'erreur est due au fait que le premier paramètre est de type Class.

public Object get(Class clazz, Serializable id) 
      throws HibernateException 

Q3. Comment convertir les T à T.class?

+1

S'il vous plaît ne nous dit pas ce que la compilation erreur est, c'est beaucoup plus amusant à deviner. – skaffman

+0

Désolé, je n'ai pas compris. Êtes-vous sérieux ou était-ce un sarcastique: S – HanuAthena

+0

C'était le sarcasme. Et en ce qui concerne Q3, les informations de type Generics sont effacées au moment de la compilation et ne sont donc pas disponibles au moment de l'exécution. Vous devez passer la classe actuelle et la mémoriser là où vous en avez besoin. – hiergiltdiestfu

Répondre

2

Les génériques ne peuvent pas être utilisés de cette manière. Modifiez votre GenericDAOImpl pour avoir un constrctor qui prend la classe et utilise cette classe dans l'appel session.get. Voir l'exemple ci-dessous (il utilise JPA au lieu de classes spécifiques Hibernate).

public class GenericDao<T> { 

    @PersistenceContext 
    private EntityManager em; 

    public EntityManager em() { 
     return em; 
    } 

    public void create(final T entity) { 
     em.persist(entity); 
    } 

    public void update(final T entity) { 
     em.merge(entity); 
    } 

    protected T get(final Class<T> type, final String id) { 
     return em.find(type, id); 
    } 

    public void delete(final T entity) { 
     em.remove(entity); 
    } 

} 

public class PersonDao extends GenericDao<Person>{ 

    public Person get(final String id) { 
     return get(Person.class, id); 
    } 

} 

En outre, il est préférable de mettre @Transactional annotations sur les services d'affaires ou de données, et non sur OTI.

4

L'astuce suivante est souvent utilisé dans les classes génériques de DAO pour accéder aux paramètres de type de sous-classes réelles:

public abstract class GenericDAO<T, ID extends Serializable> { 
    private Class<T> persistentClass; 
    ... 

    @SuppressWarnings("unchecked") 
    public GenericDAO() { 
     this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
    } 

    public T get(ID id) { 
     return (T) session.get(persistentClass, id); 
    } 

    ... 
} 

Et la sous-classe DAO réelle:

public class FooDAO extends GenericDAO<Foo, Long> {}