2010-08-26 40 views
0

我正在尝试使用Hibernates上下文会话实现通用DAO。以下是我的镜头:|如何使用Hibernate上下文会话创建通用DAO类

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> 

我们的是我们正在试图使用Spring 3.0.3落实和Hibernate 3.5.5新的应用程序。

Q1。虽然我确实实施了它并且正在开展工作,但我是否以正确的方式进行了操作? Q2302。如何使用泛型实现find()操作?

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

此行是给编译错误。

UPDATE:错误是因为第一个参数的类型为Class

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

Q3。如何把T转换成T.class

+1

请不要告诉我们什么编译错误是,猜测更有趣。 – skaffman 2010-08-26 08:59:46

+0

对不起,我没有得到。你是认真的还是那个讽刺的人:S – HanuAthena 2010-08-26 09:16:39

+0

这是讽刺。而关于Q3,泛型类型信息在编译时会被擦除,因此在运行时不可用。你需要通过实际的课程并将其记忆在你需要的地方。 – hiergiltdiestfu 2014-05-27 14:29:11

回答

2

仿制药不能以这种方式使用。改变你的GenericDAOImpl让一个constrctor在session.get调用中获得这个类并使用那个类。看下面的例子(它使用JPA而不是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); 
    } 

} 

而且,最好是把@Transactional注解业务或数据服务,而不是DAO的。

4

下面的技巧是通用的DAO类往往用来访问实际的子类的类型参数:

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

    ... 
} 

和实际DAO子类:

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