Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何防止客户端应用程序中重复出现EntityManager事务代码(打开、提交、关闭)?_Java_Database_Hibernate_Postgresql - Fatal编程技术网

Java 如何防止客户端应用程序中重复出现EntityManager事务代码(打开、提交、关闭)?

Java 如何防止客户端应用程序中重复出现EntityManager事务代码(打开、提交、关闭)?,java,database,hibernate,postgresql,Java,Database,Hibernate,Postgresql,有没有更好的方法来编写数据库方法,而不必总是获取实体管理员、开始事务、提交、关闭等 private updateDB() { EntityManager em = EntityManagerFactory.get(); em.getTransaction().begin(); //do some DB stuff em.getTransaction().commit(); em.close();

有没有更好的方法来编写数据库方法,而不必总是获取实体管理员、开始事务、提交、关闭等

private updateDB() {
        EntityManager em = EntityManagerFactory.get();
        em.getTransaction().begin();

        //do some DB stuff        

        em.getTransaction().commit();
        em.close();
}
它必须在没有任何应用服务器的情况下工作,只有一个本地客户端JavaSE应用程序。

您可以使用一个和一个接口回调来实现模板方法

这种模板方法模式的一个简短示例如下所示:

public class TransactionTemplate {

    public <T> T execute(Callable<T> doInTransaction) throws Exception {
        EntityManager em = EntityManagerFactory.get();
        EntityTransaction transaction = em.getTransaction();
        transaction.begin();

        try {
            T result = doInTransaction.call();
            transaction.commit();
            return result;
        } catch(/* Some exception that causes a rollback */ e) {
           transaction.rollback();
           throw e;
        } finally {
           em.close();
        }
    }
}
公共类事务模板{
public T execute(可调用的doInTransaction)引发异常{
EntityManager em=EntityManager工厂.get();
EntityTransaction=em.getTransaction();
transaction.begin();
试一试{
T result=doInTransaction.call();
commit();
返回结果;
}catch(/*导致回滚的某个异常*/e){
transaction.rollback();
投掷e;
}最后{
em.close();
}
}
}
在代码中,您可以这样使用它

private updateDB() {
   TransactionTemplate transaction = ... // get it somehow;
   transaction.execute(new Callable<Void>(){

        // will be executed in a transaction
        public Void call() throws Exception {
            //do some DB stuff  
        }
   });
}  
private updateDB(){
TransactionTemplate transaction=…//以某种方式获取它;
transaction.execute(newcallable()){
//将在事务中执行
public Void call()引发异常{
//做一些数据库的事情
}
});
}  
注意:这与spring的
事务模板使用的模式完全相同。所以,如果你能使用spring,你将免费获得它

根据用户311525评论进行编辑

没有传递对它的引用。例如,如果操作是persist(),它将如何执行。。。我猜有必要使用ThreadLocal`

有几种方法可以使
实体管理器
引用可用于
可调用

  • 使用注释中建议的用户311525的
    ThreadLocal
  • 不要使用标准的
    Callable
    引入自己的接口,例如
    EMAwareCallable.call(EntityManager)
  • 如果
    可调用的
    是匿名类,则通过封闭类的最后一个变量提供它
  • 创建一个实现
    Callable
    的类,并添加一个构造函数来传递对它的引用

  • 每种方法在实现工作、可测试性、可扩展性(标准java接口与否)等方面都有其优缺点。这取决于您的选择。

    我认为最好将您的数据置于事务的保护之下,这样可以使您的数据具有集成和回滚安全性!所以你只想玩DB,玩得开心!我可以在不在任何服务器上运行的客户端应用程序中使用Spring吗?如果是,那么春天可能是我的选择?=@membersound是的,你可以。看看@membersound,你也可以像普通类一样使用很多spring类,而不需要启动应用程序上下文。因此,我也可以用
    @Transactional
    注释我的DB方法。我可以吗?@membersound是的,你可以使用
    @Transactional
    。因为spring默认使用java代理,所以必须创建db类实现的接口。然后可以在spring上下文xml中定义db impl,并启用基于spring注释的事务管理。然后,如果您从应用程序上下文请求db access对象,Spring将创建一个事务感知代理。