可重用的Hibernate EntityManager(J2SE)

时间:2009-09-13 14:36:10

标签: java hibernate

我们正在开发一个J2SE应用程序,我们正在使用Hibernate作为持久层。对于我们的数据库访问,我创建了一个单例类,它具有从数据库中获取和持久化对象的所有必要方法。但是,一旦我创建了获取对象的第二种方法,我立即意识到我有一个有臭味的代码:

public enum DataManager {
  Instance;

  public List<Employee> getEmployees() {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    List<?> ems = em.createQuery("select e from Employee e").getResultList();
    List<Employee> result = new ArrayList<Employee>();
    for (Object o : ems )
      result.add((Employee) o);

    tx.commit();
    em.close();
    emf.close();
    return result;
  }

  public List<Shift> getShifts() {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    List<?> ems = em.createQuery("select s from Shift s").getResultList();
    List<Shift> result = new ArrayList<Shift>();
    for (Object o : ems )
      result.add((Shift) o);

    tx.commit();
    em.close();
    emf.close();

    return result;
  }
}

所以我肯定需要重新设计它。 Hibernate文档有一个用于会话处理和事务的HibernateUtility类。但我使用EntityManager。

就在昨天,我发现了一篇名为Generic DAO pattern with JDK 5.0的非常有趣的文章。它写于2005年,所以我真的不确定它是否仍然有效。它再次使用Sessions。

这是你用的吗?如果没有,有更好的解决方案吗?

谢谢。

注1:我对Hibernate相当新 注2:标题似乎不正确

4 个答案:

答案 0 :(得分:3)

我强烈建议你使用Spring来configure and manage你的EntityManager单例。没有气味。这类问题是一种令人烦恼的机制,真的没有必要担心。

答案 1 :(得分:1)

如果您的容器可识别EJB,或者您使用的是spring,则可以请求EntityManagerFactory。

@PersistenceUnit private EntityManagerFactory emf;

另一种选择是使用Spring或任何其他IoC来注入EntityManagerFactoryEntityManager(使用正确的范围)。

EMF是线程安全的,因此您可以在整个应用程序中共享实例。无需为每个操作重新创建一个。 EM(EntityManager)不是线程安全的,所以除非你想通过“定义”进行同步(你没有),否则它是不可重用的。

请看下面的链接,它提供了有关该主题的良好信息。 https://blueprints.dev.java.net/bpcatalog/ee5/persistence/webonlyapp.html

恕我直言,最好的方法是使用IoC来处理EntityManager和/或EntityManagerFactory的注入。

答案 2 :(得分:0)

避免编写相同的会话/事务打开和关闭的一种可能方法是在J2EE环境中使用容器,或者使用Spring将所有方法包装在类中。你也可以使用JPA and Hibernate annotations with Spring,这提供了一个很好的处理方式。我一直更喜欢Spring,因为它提供了我想要的控制级别,并且允许我将数据访问器之类的东西注入服务级别类,尽管还有其他方法可以做到这一点。

答案 3 :(得分:0)

简单的重构是将公共代码提取到单个实用程序方法:

public List<Employee> getEmployees() {
    return getObjects("Employee", Employee.class);
}

private <T> List<T> getObjects(String typeName, Class<T> typeClass) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    List<?> ems = em.createQuery("select o from " + typeName + " o").getResultList();
    List<T> result = new ArrayList<T>();
    for (Object o: ems)
      result.add(typeClass.cast(o));
    tx.commit();
    em.close();
    emf.close();
    return result;
  }

这会解决令你不安的气味吗?或者还有更多?