springマルチスレッド事務の問題


スレッドはスプリングチューブに属していないので、スレッドはスプリングを使用するトランザクションをデフォルトではできません.また、スプリング注入のバーンを取得することもできません.
spring宣言式事務管理の方法でマルチスレッドを開き、マルチスレッド内の方法は事務的に制御されない.
 
スレッド内でinsertメソッドを呼び出します.springはinsert方法を事務に入れません.
insertメソッドに@Transationコメントを入れても機能しません.
(分かりません.serviceAを複数例に変えてみましたが、だめです.)
@Service
public class ServiceA {
 
    @Transactional
    public void threadMethod(){
        this.insert();
         System.out.println("main insert is over");
        for(int a=0 ;a<3;a++){
            ThreadOperation threadOperation= new ThreadOperation();
            Thread innerThread = new Thread(threadOperation);
            innerThread.start();
        }
    }
 
    public  class ThreadOperation implements Runnable {
        public ThreadOperation(){
        }
        @Override
        public void run(){
            insert();
            System.out.println("thread insert is over");
        }
    }
 
    public void insert(){
 
    //do insert......
 
    }
}
 
 
上のinsert方法を新しいクラスに出したら、事務の注釈を入れて、事務管理にinsert方法を入れることに成功します.
@Service
public class ServiceA {
 
@Autowired
private ServiceB serviceB;
 
    @Transactional
    public void threadMethod(){
        this.insert();
        System.out.println("main insert is over");
        for(int a=0 ;a<3;a++){
            ThreadOperation threadOperation= new ThreadOperation();
            Thread innerThread = new Thread(threadOperation);
            innerThread.start();
        }
    }
 
    public  class ThreadOperation implements Runnable {
        public ThreadOperation(){
        }
        @Override
        public void run(){
            serviceB.insert();
            System.out.println("thread insert is over");
        }
    }
 
    public void insert(){
 
        //do insert......
 
    }
}
 
@Service
public class ServiceB {
 
    @Transactional
    public void insert(){
 
        //do insert......
 
    }
 
}
 
 
 
また、マルチスレッド事務を使う場合は、ロールバックを行うのが面倒くさいです.
threadのrun方法には、例外があります.例外はありませんが、異常にスレッドが停止します.
最も面倒なのは、スレッド内で投げられた異常がメインスレッドにtry…catchを使ってもカットできないことです.
これは非常に悪いです.私たちは異常を感知しなければなりません.例えば、あるスレッドが重要な事務を処理しています.threadが異常終了したら、異常な報告を受けなければなりません.
この時スレッドのUncaught Exception Handlerを使用して異常処理を行うことができ、Uncaght Exception Handlerの名前は未捕獲の異常を処理することを意味します.より明確には、捕獲されていない運転時の異常を処理します.
 
以下のコード
スレッドが出たら使用します
①に異常を投げかける
②で異常をキャッチし、RuntimeExceptionをスローする
③手動処理ロールバックロジック
@Service
public class ServiceA {
 
@Autowired
private ServiceB serviceB;
 
    @Transactional
    public void threadMethod(){
        this.insert();
        System.out.println("main insert is over");
        for(int a=0 ;a<3;a++){
            ThreadOperation threadOperation= new ThreadOperation();
            Thread innerThread = new Thread(threadOperation);
            innerThread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
               public void uncaughtException(Thread t, Throwable e) {
                   try {
                        serviceB.delete();③
                   } catch (Exception e1) {
                       e1.printStackTrace();
                   }
               }
            });
            innerThread.start();
        }
    }
 
    public  class ThreadOperation implements Runnable {
        public ThreadOperation(){
        }
        @Override
        public void run(){
            try {
               serviceB.insert();
           }catch (Exception ex){ ②
            System.out.println(" Exception in run ");
               throw new RuntimeException();
           }
            System.out.println("thread insert is over");
        }
    }
 
    public void insert(){
 
        //do insert......
 
    }
}
 
@Service
public class ServiceB {
 
    @Transactional
    public void insert() throws Exception{ ①
 
    //do insert......
 
    }
 
    @Transactional
    public void delete() throws Exception{ 
 
        //do delete......
 
    }
 
}