0

SpringsのTaskExecutorクラスを使用して、データベース内のいくつかのエントリの非同期削除を実行しています。したがって、基本的に、基になるクラスのexecuteメソッドは、非同期削除を実行するスレッドとして実行されます。

このメソッドでは、データベースエントリの削除を実行するBeanメソッドを呼び出します。BeanメソッドにあるデフォルトのTransaction属性を使用していますPROPAGATION.REQUIRED。基礎となるのは、私が話しているexecuteメソッドです。基本的に、callig 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メソッドでスタックすることがあります。何が起こっているのか理解できません。誰か助けてください。

4

1 に答える 1

3

DB レベルで何が起こっているのかを理解する必要があります。まず、新しいスレッドを開始するため、Spring に真新しいトランザクションを要求する必要があります (つまりTransactionDefinition.PROPAGATION_REQUIRES_NEW、 の代わりにTransactionDefinition.PROPAGATION_NESTED)。

つまり、データベースからすべての Beanを再度取得する必要があります (無効になった最初のトランザクションでそれらを読み取るため)。キャッシュにはまだそれらが含まれているため、これは思ったほど高価ではありません。外部トランザクションから取得した Bean の ID を使用して再度ロードするだけです。通常は、すべての ID を収集し、外側のトランザクションを閉じて (ロックを解除するため)、内側のスレッドを開始することをお勧めします。

なぜ新規取引?(削除スレッドを開始した)他のスレッドが最終的に完了し、外部トランザクションを閉じるためです。これは削除スレッドの制御外であるため、いつでも発生する可能性があります。

削除しようとしている Bean の 1 つを別のスレッドがロックしているよりも、削除スレッドがハングした場合。ORM フレームワークの SQL ロギングを有効にして、SQL ブロックを確認します。これにより、どこを見ればよいかがわかります。

于 2010-12-06T12:44:52.527 に答える