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 インジェクションを使用することをお勧めします。