2010-08-26 73 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> {}