我们正在开发一个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:标题似乎不正确
答案 0 :(得分:3)
我强烈建议你使用Spring来configure and manage你的EntityManager单例。没有气味。这类问题是一种令人烦恼的机制,真的没有必要担心。
答案 1 :(得分:1)
如果您的容器可识别EJB,或者您使用的是spring,则可以请求EntityManagerFactory。
@PersistenceUnit private EntityManagerFactory emf;
另一种选择是使用Spring或任何其他IoC来注入EntityManagerFactory
或EntityManager
(使用正确的范围)。
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;
}
这会解决令你不安的气味吗?或者还有更多?