gpt4 book ai didi

java - 使用 Spring 的事务管理器进行回滚

转载 作者:行者123 更新时间:2023-12-02 00:48:05 25 4
gpt4 key购买 nike

我正在使用Springs的TaskExecutor类来执行异步删除数据库中的一些条目。所以基本上底层类的execute方法作为线程运行来执行异步删除。

在此方法中,我调用执行数据库条目删除操作的 bean 方法。我使用默认事务属性 PROPAGATION.REQUIRED在bean方法中。底层是我正在谈论的执行方法。基本上,一旦调用bean方法后发生任何异常或者有人取消删除任务,我需要回滚整个数据库事务。

 package com.ibm.security.modeling.async.tasks;

import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;

import com.ibm.security.modeling.async.AsynchronousTask;
import com.ibm.security.modeling.async.AsynchronousTaskType;
import com.ibm.security.modeling.data.analysis.ModelingManager;
import com.ibm.security.modeling.data.analysis.ProjectManager;
import com.ibm.security.modeling.data.entity.Model;
import com.ibm.security.modeling.data.entity.ModelStatus;
import com.ibm.security.modeling.data.entity.Project;
import com.ibm.security.modeling.i18n.msgs.LogMessages;


public class DeleteProjectTask extends AbstractDeletionTask implements AsynchronousTask
{
private static final String CLASS_NAME = DeleteProjectTask.class.getName();
private static final Logger LOG = Logger.getLogger(CLASS_NAME);


private String projectName;
private Collection<Model> modelCol;
private ProjectManager pMgr = null;
private long projectId = 0L;
private Project project=null;
private PlatformTransactionManager txManager;

public DeleteProjectTask(ProjectManager pMgr, ModelingManager mMgr, long pid)
{
super(pMgr.getProject(pid).getName(), mMgr);
this.project =pMgr.getProject(pid);
this.projectName = project.getName();
this.pMgr = pMgr;
this.projectId = pid;
this.modelCol=project.getModels();
this.txManager=(PlatformTransactionManager)SpringUtils.getFactory().getBean("txManager");
}

public AsynchronousTaskType getTaskType()
{
return AsynchronousTaskType.PROJECT_DELETION;
}


public void execute()
{
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
TransactionStatus status = txManager.getTransaction(def);
System.out.println(status.isRollbackOnly());
boolean success = false;
try
{
//recordMessage("execute", LogMessages.PROJECT_DELETE_UNDERGOING, new String[]{projectName},1);
for (Model mo:this.modelCol){
checkForCancellation();
//System.out.println("hello");
//recordMessage("execute", LogMessages.PROJECT_DELETE_UNDERGOING, new String[]{projectName},mo.getId());
//System.out.println("hello");
pMgr.deleteModel(projectId,mo.getId());
System.out.println("66666666666666666666");
}
checkForCancellation();
System.out.println("%%%%%%%%%%%%%%%%%%%%%%");
// pMgr.deleteModel(, modelId)
pMgr.deleteProject(projectId);
System.out.println("$$$$$$$$$$$$$$$$");
// recordMessage("execute", LogMessages.PROJECT_DELETE_COMPLETE_SUCCESS,
// new String[]{projectName},1L);
success = true;
//throw new Exception();
}
catch (TaskCanceledException e)
{
//Informational message that project creation was canceled

//recordMessage("execute", LogMessages.PROJECT_DELETE_CANCELED, new String[]{projectName},0L);
}
catch (Throwable t)
{
LOG.log(Level.INFO, "caught throwable while deleting project " + projectId, t);
if (t instanceof IncorrectResultSizeDataAccessException)
{
// runtime exception indicating that the project could not be located
// during the status update or copy process
// recordErrorMessage("execute", LogMessages.PROJECT_DELETE_FAILED_INTEGRITY, new String[]{projectName},0L);
}
else
{
// some other unexpected error occurred - log error
// recordErrorMessage("execute", LogMessages.PROJECT_DELETE_FAILED_UNKNOWN, new String[]{projectName},0L);
}
}
finally
{
//if not successful, attempt to mark the project as failed
if (!success)
{
System.out.println("i am here4:"+success);
txManager.rollback(status);
System.out.println("am");
}else{
System.out.println("i am here3:"+success);
txManager.commit(status);
}
}
}


}

但是事情并没有按预期工作。事实上,每次的结果也不一致,即有时代码会卡在 bean 方法中。我无法理解发生了什么......请有人帮忙

最佳答案

您必须了解数据库级别发生的情况。首先,由于您启动了一个新线程,因此必须向 Spring 请求一个全新的事务(即 TransactionDefinition.PROPAGATION_REQUIRES_NEW 而不是 TransactionDefinition.PROPAGATION_NESTED)。

这意味着您必须从数据库再次获取所有bean(因为您使用第一个不再有效的事务读取它们)。这并不像听起来那么昂贵,因为您的缓存仍然包含它们。只需使用从外部事务获取的 bean ID 再次加载它们即可。通常最好收集所有 ID,关闭外部事务(以摆脱任何锁定),然后启动内部线程。

为什么要进行新交易?因为另一个线程(启动删除线程)最终将完成并关闭外部事务。这不受删除线程的控制,因此随时可能发生。

如果删除线程挂起,则说明另一个线程锁定了您尝试删除的某个 Bean。为您的 ORM 框架启用 SQL 日志记录以查看哪些 SQL block 。这应该会让您知道去哪里寻找。

关于java - 使用 Spring 的事务管理器进行回滚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4366399/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com