Как создать общий класс DAO, используя сеансы Hibernate Context - PullRequest
0 голосов
/ 26 августа 2010

Я пытаюсь реализовать общий DAO, используя сеансы контекста Hibernates.Вот мой снимок: |

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.Хотя я это реализовал и работает, я сделал правильно?

Q2.Как я могу реализовать операцию find() с использованием шаблонов?

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

В этой строке выдается ошибка компиляции.

ОБНОВЛЕНИЕ : ошибка в том, что первый параметр имеет тип Class.

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

Q3.Как конвертировать T в T.class?

Ответы [ 2 ]

4 голосов
/ 26 августа 2010

Следующий прием часто используется в общих классах 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 голосов
/ 26 августа 2010

Обобщения не могут быть использованы таким образом.Измените ваш 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.

...