在DAO图层类中,假设我的代码如下:
private EntityManagerFactory factory;
public void update(T entity) {
EntityManager entityManager = factory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.merge(entity);
entityManager.getTransaction().commit();
entityManager.close();
}
现在在上面的代码块中,可能会在调用entityManager.close()之前(很少)发生RuntimeExceptions。所以,这样写它会很好:
public void update(T entity) {
EntityManager entityManager = factory.createEntityManager();
try {
entityManager.getTransaction().begin();
entityManager.merge(entity);
entityManager.getTransaction().commit();
}
finally {
entityManager.close();
}
}
由于我方法中的所有对象都是本地的,因此一旦方法结束,它们就不会存在。那么,当方法内发生异常时,该方法的堆栈会发生什么?
我认为如果在异常的情况下堆栈存在,那么我确实需要finally块来关闭entityManager。实际发生了什么?
答案 0 :(得分:4)
由于我方法中的所有对象都是本地的,因此一旦方法结束,它们就不会存在。
不,对象的引用是本地的,并且在方法范围完成时被删除,对象本身驻留在堆上,最终可能被垃圾回收。为了安全起见,我将在finally语句中添加对close()的调用。
看一下Hibernate 4.2.15的EntityManager.close()
实现(我们不能使用Hibernate 4.3+但我猜它看起来很相似), close被传递给会话,事务协调器和 - 如果启用 - 统计信息收集器。所有这些类都将自己进行一些清理,无论是清除第一级缓存,关闭数据库连接,收集会话统计信息等。
答案 1 :(得分:3)
由于我方法中的所有对象都是本地的,因此它们不会存在一次 方法结束了。
在Java中,对象一直存在,直到垃圾收集器销毁它们。在声明对象的引用的范围的最终确定时,这不是必要的(通常,您无法预测对象何时将被垃圾收集)。因此,您应该关闭EntityManager。
无论如何,try with resources可能是个更好的主意。
try-with-resources语句是一个声明一个的try语句 或更多资源。资源是必须在之后关闭的对象 程序结束了。
答案 2 :(得分:1)
RuntimeExceptions可能会在(很少)之前发生 entityManager.close()被调用
如果您可以采取任何措施来处理您期望的RuntimeException
,那么您甚至可以捕获并处理它们。如果你不能在那种情况下最终将是安全选项,以便关闭资源。如果它(EntityManager
)实现Closeable
接口,您还可以考虑自动调用关闭的try-with-resource
语句。
答案 3 :(得分:0)
令我困惑的是,我发现的所有例子都没有使用finally子句。甚至在Hibernate或JPA的官方文档中。
在我看来,正确的代码应该始终使用finally子句。我没有正确地将实体映射到数据库表,并且在不使用finally子句时挂起了(Java SE)应用程序。
EntityManagerFactory
和EntityManager
都不能像某些人所建议的那样使用try-with-resources;它们不是AutoCloseable
。
修改我找到了一个doing it correctly的示例。 Heureka。
package com.zetcode;
import com.zetcode.model.City;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class Application {
private static final String PERSISTENCE_UNIT_NAME = "my-pu";
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager entityManager = emf.createEntityManager();
try {
entityManager.getTransaction().begin();
Query query = entityManager.createQuery("SELECT c FROM City c");
List<City> countries = query.getResultList();
countries.stream().forEach((x) -> System.out.println(x));
entityManager.getTransaction().commit();
} finally {
entityManager.close();
emf.close();
}
}
}