Java 如何在事务存在的情况下使代码重用成为可能?

Java 如何在事务存在的情况下使代码重用成为可能?,java,Java,在通过Java创建用于在MySQL数据库上运行查询的API时,我以以下方式创建了包含在Hibernate会话和事务中的多个方法: public void methodA(){ //会话和事务 hbu.createSession(); hbu.beginTransaction(); //代码在这里 hbu.commitTransaction(); hbu.closeSession(); } 然而,我似乎无法从其他类似的方法调用这些方法。我遇到的错误如下: Exception in thread

在通过Java创建用于在MySQL数据库上运行查询的API时,我以以下方式创建了包含在Hibernate会话和事务中的多个方法:

public void methodA(){
//会话和事务
hbu.createSession();
hbu.beginTransaction();
//代码在这里
hbu.commitTransaction();
hbu.closeSession();
}
然而,我似乎无法从其他类似的方法调用这些方法。我遇到的错误如下:

Exception in thread "main" java.lang.IllegalStateException: Transaction already active
我的理解是,您不能在已经创建的会话中创建会话。我可以复制被调用方法的代码并防止这种情况,但是,这显然会导致大量重复代码。
处理这个问题的标准方法是什么?

将事务处理集中在一个地方,然后将其他所有内容作为lambda传入怎么样?因此,您只在一个地方拥有所有必要的试捕/最终捕获功能

    void transactional(Runnable r) {
        hbu.createSession();
        try {
            hbu.beginTransaction();
            try {
                r.run();
                hbu.commitTransaction();
            } catch (Exception e) {
                hbu.rollbackTransaction();
                // perhaps re-throw exception here
            }
        } finally {
            hbu.closeSession();
        }
    }

    void doSmthg(){
    }

    void doSmthgElse(){
        doSmthg();
    }

    void useTransactional(){
        transactional(() -> {
            doSmthg();
            doSmthgElse()
        });

        transactional(() -> doSmthg());
    }

您还可以进一步将
transactional()
拆分为两个方法,一个用于会话控制,另一个用于事务控制,以在单个会话中获取嵌套事务。

将事务处理集中在一个位置,并将其他所有内容作为lambda传入怎么样?因此,您只在一个地方拥有所有必要的试捕/最终捕获功能

    void transactional(Runnable r) {
        hbu.createSession();
        try {
            hbu.beginTransaction();
            try {
                r.run();
                hbu.commitTransaction();
            } catch (Exception e) {
                hbu.rollbackTransaction();
                // perhaps re-throw exception here
            }
        } finally {
            hbu.closeSession();
        }
    }

    void doSmthg(){
    }

    void doSmthgElse(){
        doSmthg();
    }

    void useTransactional(){
        transactional(() -> {
            doSmthg();
            doSmthgElse()
        });

        transactional(() -> doSmthg());
    }

您还可以进一步将
transactional()
拆分为两个方法,一个用于会话控制,另一个用于事务控制,以在单个会话中获取嵌套事务。

有3种方法可以实现此目的

第一个是JTA,但您需要一个支持它的容器

第二种方法依赖于Hibernate SessionFactory的getCurrentSession()方法

getCurrentSession()
将返回一个作用域会话(通常每个线程一个)

一旦您有了会话,您就可以获得事务,并且您可以测试事务是否已经开始。如果有一个事务正在进行,则跳过开始和结束事务

但最好的办法是不要在方法中启动事务

如果现在有methodA()和methodB()来启动和提交/回滚事务,那么应该将begin和commit/rollback移动到这些方法的调用方

实际上,调用方是否知道什么是事务,而不是实现某种原子操作的单一方法

因此,使用会话的方法不应该启动或结束会话,调用方应该这样做

例如,对于web应用程序,您可以在请求开始时开始事务,并在请求结束时提交结果


如果发生任何异常,您应该通过回滚来清理会话。

有3种方法

第一个是JTA,但您需要一个支持它的容器

第二种方法依赖于Hibernate SessionFactory的getCurrentSession()方法

getCurrentSession()
将返回一个作用域会话(通常每个线程一个)

一旦您有了会话,您就可以获得事务,并且您可以测试事务是否已经开始。如果有一个事务正在进行,则跳过开始和结束事务

但最好的办法是不要在方法中启动事务

如果现在有methodA()和methodB()来启动和提交/回滚事务,那么应该将begin和commit/rollback移动到这些方法的调用方

实际上,调用方是否知道什么是事务,而不是实现某种原子操作的单一方法

因此,使用会话的方法不应该启动或结束会话,调用方应该这样做

例如,对于web应用程序,您可以在请求开始时开始事务,并在请求结束时提交结果


如果发生任何异常,则应通过回滚清理会话。

您可以传递一个标志,指示是否应使用新会话和/或事务。您还可以研究为您提供大量事务处理的框架(例如JPA),您可以传递一个标志,指示是否应该使用新会话和/或事务。您还可以研究为您提供大量事务处理的框架(例如JPA)。