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