1. 発生した問題
1 つのメソッドで複数のデータベース保存操作を行うと、中間のデータベース操作でエラーが発生します。疑似コードは次のとおりです:
public method() { Dao1.save(Person1); Dao1.save(Person2); Dao1.save(Person2);//假如这句发生了错误,前面的两个对象会被保存到数据库中 Dao1.save(Person2); }
期待的情况:发生错误之前的所有数据库保存操作都回滚,即不保存 正常情况:前面的数据库操作会被执行,而发生数据库操作错误开始及之后的所有的数据保存操作都将失败。这样子应该都不是我们要的结果吧。 当遇到这种情况,我们就可以使用Spring的事务解决这个问题。 2、异常的一些基本知识 1) 异常的架构 异常的继承结构:Throwable为基类,Error和Exception继承Throwable,RuntimeException和IOException等继承Exception。Error和RuntimeException及其子类成为未检查异常(unchecked),其它异常成为已检查异常(checked)。
2) エラー例外
エラーは、プログラムの実行中に非常に深刻で回復不可能なエラーが発生したことを示します。この場合、アプリケーションは次のような操作を終了することしかできません。 JAVA 仮想マシンのエラー。 Error はチェックされていない例外であり、コンパイラは Error が処理されたかどうかをチェックしないため、プログラム内で Error タイプの例外をキャッチする必要はありません。通常の状況では、プログラム内で Error タイプの例外がスローされるべきではありません。
3) RuntimeException
例外には、RuntimeException とその他の RuntimeException 以外の例外が含まれます。
RuntimeException は Unchecked Exception であり、プログラムが RuntimeException を処理するかどうかをコンパイラがチェックしないことを意味します。プログラム内で RuntimException 型の例外をキャッチする必要はなく、メソッド本体で RuntimeException クラスを宣言する必要もありません。 。 RuntimeException が発生した場合は、プログラム内でプログラミング エラーが発生したことを意味するため、RuntimeException をキャッチするのではなく、エラーを見つけてプログラムを変更する必要があります。
4) チェック済み例外
チェック済み例外。これはプログラミングで最もよく使用される例外でもあり、Exception から継承され、RuntimeException ではないすべての例外がチェック済み例外、IOException、および ClassNotFoundException です。 JAVA 言語では、チェックされた例外を処理する必要があると規定されており、コンパイラはこれをチェックし、メソッド本体でチェックされた例外を宣言するか、catch ステートメントを使用してチェックされた例外を処理用にキャプチャします。それ以外の場合は、コンパイルできません。
3. 例
ここで使用されるトランザクション設定は次のとおりです:
<!-- Jpa 事务配置 --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <!-- 开启注解事务 --> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
Spring 設定ファイルで、データ ソースのdefaultAutoCommit が True に設定されている場合、メソッドが例外をキャッチすると、トランザクションは実行されません。 rollback 、自分で例外をキャッチしない場合、次の例のようにトランザクションはロールバックされます
たとえば、設定ファイルにそのようなレコードがある場合
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="xxx" value="xxx"/> <property name="xxx" value="xxx"/> .... <property name="defaultAutoCommit" value="true" /> </bean>
おそらく、ロールバックされていないことがわかるでしょう。このパラメータを設定すると、自動的に送信されませんか? 答えは「いいえ」です。データベース接続プールとして com.alibaba.druid.pool.DruidDataSource を使用します。以下のソース コードを参照してください。
その場合、状況は 2 つありますケース 1: プログラム内で手動で例外をキャッチする機能がない場合
@Transactional(rollbackOn = { Exception.class }) public void test() throws Exception { doDbStuff1(); doDbStuff2();//假如这个操作数据库的方法会抛出异常,现在方法doDbStuff1()对数据库的操作 会回滚。 }
@Transactional(rollbackOn = { Exception.class }) public void test() { try { doDbStuff1(); doDbStuff2();//假如这个操作数据库的方法会抛出异常,现在方法doDbStuff1()对数据库的操作 不会回滚。 } catch (Exception e) { e.printStackTrace(); } }
@Transactional(rollbackOn = { Exception.class }) public void test() { try { doDbStuff1(); doDbStuff2(); } catch (Exception e) { e.printStackTrace(); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//就是这一句了,加上之后,如果doDbStuff2()抛了异常, //doDbStuff1()是会回滚的 } }