0

Spring 宣言型トランザクションの基本をテストするために、単純な Spring アプリケーションを作成しました。ルールに従って、RuntimeException の場合、宣言型トランザクションはロールバックする必要があります。しかし、私の場合はロールバックしていませんでした。

メインのテスト クラスにはコードがあります

public class SpringOraTest {
public static void main(String[] args) {
    ApplicationContext aplctx= new     
FileSystemXmlApplicationContext("src\\config\\SpringConfigForOra.xml");

    //Call to test Declarative Transaction with Annotation
TrxHandleAnnotated prxyobj=((TrxHandleAnnotated)aplctx.getBean("dbCommandAnnotated"));
prxyobj.doTask();
}
}

クラス TrxHandleAnnotated にはコードがありました:-

@Transactional
public class TrxHandleAnnotated
public void doTask(){
 ApplicationContext aplctx= new  
 FileSystemXmlApplicationContext("src\\config\\SpringConfigForOra.xml");   
 JdbcTemplate jdbcTemplate= (JdbcTemplate)aplctx.getBean("jdbcTemplate");

 jdbcTemplate.update("insert into kau_emp values(4,'forthmulga' )");

 throw new RuntimeException();
}

そして、構成 XML に必要な構成がありました。

例外がスローされたときにトランザクションがロールバックされることを期待していました。しかし、それはロールバックされず、レコードは DB にコミットされていました。

インターネットで長い間検索した後でも、なぜロールバックされないのか理解できませんでした。

後で、doTask() コードでコンテキストをもう一度作成し、新しいコンテキストから JdbcTemplate インスタンスを取り出していることに気付きました。これが問題の根本原因でした。

両方のクラスが何らかのコンテキストを使用するようにコードを変更しました。そして、それはうまくいきました!!!

public class SpringOraTest {
public static ApplicationContext aplctx;
public static void main(String[] args) {
  aplctx= new FileSystemXmlApplicationContext("src\\config\\SpringConfigForOra.xml");

  //Call to test Declarative Transaction with Annotation
  TrxHandleAnnotated prxyobj=    
((TrxHandleAnnotated)aplctx.getBean("dbCommandAnnotated"));
prxyobj.doTask();
}

@Transactional
public class TrxHandleAnnotated
public void doTask(){

 JdbcTemplate jdbcTemplate=(JdbcTemplate)SpringOraTest.aplctx.getBean("jdbcTemplate");
 jdbcTemplate.update("insert into kau_emp values(4,'forthmulga' )");

 throw new RuntimeException();
}

これは、特に必要がない限り、アプリケーション全体で 1 つのコンテキスト オブジェクトのみを使用する必要があるという教訓です。

これはあまりにも明白な Spring の実践者に聞こえるかもしれませんが、私のような春の初心者は、このようなばかげた間違いを犯す可能性があります。それで、それを共有することを考えました。

この特定のケースでは、JdbcTemplate を手動で作成する代わりに、メンバー変数として宣言し、setter インジェクションを使用することをお勧めします。

4

1 に答える 1