【问题标题】:How to create a Generic DAO class using Hibernate Context sessions如何使用 Hibernate Context 会话创建通用 DAO 类
【发布时间】:2010-08-26 08:48:55
【问题描述】:

我正在尝试使用 Hibernates 上下文会话来实现通用 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();
   }
  }
 }
}

应用上下文:

<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 来实现。

第一季度。虽然我确实实施了它并且正在工作,但我的做法是否正确?

第二季度。如何使用泛型实现find() 操作?

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

此行给出编译错误。

更新:错误是因为第一个参数是Class 类型。

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

第三季度。如何将T 转换为T.class

【问题讨论】:

  • 请不要告诉我们编译错误是什么,猜的更有趣。
  • 对不起,我没听懂。你是认真的还是讽刺的:S
  • 这是讽刺。关于 Q3,泛型类型信息在编译时被删除,因此在运行时不可用。您需要通过实际的课程并将其记住在您需要的地方。

标签: java hibernate spring generics dao


【解决方案1】:

在通用 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> {}

【讨论】:

    【解决方案2】:

    不能以这种方式使用泛型。更改您的 GenericDAOImpl 以拥有一个接受该类并在 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 上。

    【讨论】:

      猜你喜欢
      • 2014-08-16
      • 2011-05-17
      • 1970-01-01
      • 2010-12-10
      • 2012-09-01
      • 2018-01-10
      • 1970-01-01
      • 2012-03-15
      • 2014-09-22
      相关资源
      最近更新 更多