Java 在这种情况下应该使用try-finally

Java 在这种情况下应该使用try-finally,java,exception,stack,try-catch,Java,Exception,Stack,Try Catch,在DAO层类中,假设我有如下代码: private EntityManagerFactory factory; public void update(T entity) { EntityManager entityManager = factory.createEntityManager(); entityManager.getTransaction().begin(); entityManager.merge(entity); entityManager.ge

在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()之前,运行时异常可能(很少)发生。那么,这样写会好吗:

public void update(T entity) {
    EntityManager entityManager = factory.createEntityManager();
    try {
        entityManager.getTransaction().begin();
        entityManager.merge(entity);
        entityManager.getTransaction().commit();
    }
     finally {
        entityManager.close();
    }
}
因为我的方法中的所有对象都是本地对象,所以一旦方法结束,它们就不存在了。那么,当异常发生在方法内部时,该方法的堆栈会发生什么变化

我认为,如果堆栈在异常情况下存在,那么我确实需要使用finally块来关闭entityManager。到底发生了什么

因为我的方法中的所有对象都是本地对象,所以一旦方法结束,它们就不存在了

不,对对象的引用是本地的,并且在方法作用域完成时被删除,对象本身驻留在堆上,最终可能被垃圾收集。为了安全起见,我将在finally语句中添加对close()的调用

查看Hibernate 4.2.15的
EntityManager.close()
实现(我们还不能/不使用Hibernate 4.3+,但我猜它看起来很相似),关闭被传递给会话、事务协调器和统计收集器(如果启用)。所有这些类都将自己进行一些清理,例如清除一级缓存、关闭数据库连接、收集会话统计信息等

因为我的方法中的所有对象都是本地对象,所以一旦方法结束,它们就不存在了

不,对对象的引用是本地的,并且在方法作用域完成时被删除,对象本身驻留在堆上,最终可能被垃圾收集。为了安全起见,我将在finally语句中添加对close()的调用

查看Hibernate 4.2.15的
EntityManager.close()
实现(我们还不能/不使用Hibernate 4.3+,但我猜它看起来很相似),关闭被传递给会话、事务协调器和统计收集器(如果启用)。所有这些类都将自己进行一些清理,例如清除一级缓存、关闭数据库连接、收集会话统计信息等

运行时异常可能在 将调用entityManager.close()

如果您可以做任何事情来处理您期望的
RuntimeException
,那么您甚至可以捕获并处理它们。如果在这种情况下您甚至不能最终关闭资源,那么将是安全的选项。如果它(<代码> EntIdMeals<代码>)实现可关闭接口,您也可以考虑<代码>尝试使用资源语句,该语句自动调用关闭。 运行时异常可能在 将调用entityManager.close()

如果您可以做任何事情来处理您期望的
RuntimeException
,那么您甚至可以捕获并处理它们。如果在这种情况下您甚至不能最终关闭资源,那么将是安全的选项。如果它(<代码> EntIdMeals<代码>)实现可关闭接口,您也可以考虑<代码>尝试使用资源语句,该语句自动调用关闭。 因为我的方法中的所有对象都是本地对象,所以它们不会一次存在 方法结束了

在Java中,对象一直存在,直到垃圾收集器将其销毁。这不一定是因为声明了对对象的引用的作用域的终结(通常,您无法预测对象何时将被垃圾收集)。因此,您应该关闭EntityManager

不管怎样,a可能是个更好的主意

try with resources语句是一个try语句,它声明了一个 或者更多的资源。资源是一个对象,必须在 程序结束了

因为我的方法中的所有对象都是本地对象,所以它们不会一次存在 方法结束了

在Java中,对象一直存在,直到垃圾收集器将其销毁。这不一定是因为声明了对对象的引用的作用域的终结(通常,您无法预测对象何时将被垃圾收集)。因此,您应该关闭EntityManager

不管怎样,a可能是个更好的主意

try with resources语句是一个try语句,它声明了一个 或者更多的资源。资源是一个对象,必须在 程序结束了


令我困惑的是,我找到的所有例子都没有使用finally子句。甚至在Hibernate或JPA的官方文档中

在我看来,正确的代码应该始终使用finally子句。我没有将实体正确映射到数据库表,并且(JavaSE)应用程序在未使用finally子句时被挂起

EntityManagerFactory
EntityManager
都不能与一些建议的try-with-resources一起使用;它们不可自动关闭

编辑我找到了一个例子。海瑞卡

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();
        }
    }
}
package com.zetcode;
导入com.zetcode.model.City;
导入java.util.List;
导入javax.persistence.EntityManager;
导入javax.persistence.EntityManagerFactory;
导入javax.persistence.persistence;
导入javax.persistence.Query;
公共类应用程序{
私有静态最终字符串持久性\u单元\u NAME=“my pu”;
公共静态void main(字符串[]args){
EntityManagerFactory emf=Persistence.createEntityManagerFactory(Persistence\u UNIT\u NAME);
EntityManager EntityManager=emf.createEntityManager();
试一试{
entityManager.getTransaction().begin();
Query Query=entityManager.createQuery(“从城市c中选择c”);
List countries=query.getResultList();
countries.stream().forEach((x)->System.out.println(x));
entityManager.getTransaction().commit();
}最后{
entityManager.close();
emf.close();