今日の仕事で春のトランザクションの問題が発生しました:サービスメソッドでは、スレッドを介してユーザーポイントとユーザーポイントログの追加を実行する必要があります@Transactional宣言型トランザクションを渡そうとしましたが機能せず、手動トランザクションのみを使用できます制御する
だから私はこの状況を記録するためにこのブログを書きました、みんなを助けることを望んでいます
1.業務の重要性、実際の開発プロセスにおいて、私たちは深い理解を持っていると思います。しかし、開発中のトランザクションを制御するためにアノテーションを使用することが多いという問題があります。率直に言って、トランザクションを調整するために、スプリングに基づく7つのトランザクション制御方法が使用されます。
2つ目は、Springの7つのトランザクション伝播動作です。
Propagation.REQUIRED | 現在のメソッドが現在のトランザクションをサポートし、呼び出し元と同じトランザクションコンテキストにあることを表します。トランザクションがない場合は、統合ロールバックをロールバックします(現在のメソッドが他のメソッドによって呼び出され、呼び出し元自体にトランザクションがある場合)。次に、新しいトランザクションを作成します。 |
---|---|
Propagation.SUPPORTS | 現在のメソッドが現在のトランザクションをサポートし、呼び出し元と同じトランザクションコンテキストにあることを表します。トランザクションがない場合は、統合ロールバックをロールバックします(現在のメソッドが他のメソッドによって呼び出され、呼び出し元自体にトランザクションがある場合)。次に、メソッドは非トランザクションコンテキストで実行されます |
Propagation.MANDATORY | 現在のメソッドが現在のトランザクションをサポートし、呼び出し元と同じトランザクションコンテキストにあることを表します。トランザクションがない場合は、統合ロールバックをロールバックします(現在のメソッドが他のメソッドによって呼び出され、呼び出し元自体にトランザクションがある場合)。その後、故障をスローします |
Propagation.REQUIRES_NEW | 新しいトランザクションコンテキストを作成します。現在のメソッドの呼び出し元がすでにトランザクションを持っている場合、呼び出し元のトランザクションは一時停止されます。2つのトランザクションは同じコンテキストにありません。それぞれで例外が発生した場合、それぞれがロールバックされます。 。 |
Propagation.NOT_SUPPORTED | メソッドは非トランザクション状態で実行されます。メソッドを呼び出す呼び出し元にトランザクションがある場合、呼び出し元のトランザクションは最初に中断されます。 |
伝播。決して | このメソッドは非トランザクション状態で実行されます。呼び出し元にトランザクションがある場合、例外がスローされます。 |
Propagation.NESTED | 現在のコンテキストにトランザクションがある場合、メソッドはネストされたトランザクションとして実行されます。つまり、メソッドのこの部分は外部メソッドの一部であり、呼び出し元はロールバックし、メソッドはロールバックしますが、メソッド自体が例外がある場合、ロールバックは外部トランザクションに影響しません。トランザクションがない場合は、PROPAGATION_REQUIREDと同じです。 |
3つ、データベースの4つの主要な特性とMySQLトランザクションの分離レベル
1)4つの特徴
a、Atomicity(Atomicity)Atomicity
は、トランザクションに含まれるすべての操作が成功または失敗してロールバックすることを意味します。
b。整合性(整合性)
整合性とは、トランザクションがデータベースを整合性のある状態から別の整合性のある状態にする必要があることを指します。つまり、トランザクションは実行の前後で整合性のある状態である必要があります。
c。分離
とは、複数のユーザーが同時にデータベースにアクセスする場合です。たとえば、同じテーブルを操作する場合、各ユーザーに対してデータベースによって開かれるトランザクションは、他のトランザクションの操作によって妨害されません。複数の同時トランザクション間で互いに分離されます。 。
d。耐久性。耐久性
とは、トランザクションがコミットされると、データベース内のデータへの変更が永続的であることを意味します。データベースシステムで障害が発生した場合でも、トランザクションをコミットする操作が失われることはありません。
2)分離レベル
a。ダーティリードとは、トランザクションプロセス中にコミットされていない別のトランザクションのデータを読み取ることを指します。(コミットされていないデータを読み取る)
b。繰り返し不可の読み取りとは、データベース内の特定のデータについて、トランザクション範囲内の複数のクエリが異なるデータ値を返したことを意味します。これは、クエリ間隔中に別のトランザクションによって変更および送信されたためです。(読み書き)
c。ファントム読み取りとは、2つのトランザクションが同時に発生し、2つのトランザクションがデータを変更し、読み取られたデータが変更を開始したデータではないことを意味します。ファントム読み取りと非反復読み取りの両方が別のコミットされたトランザクションを読み取ります(これはダーティ読み取りとは異なります)。違いは、非反復読み取りクエリはすべて同じデータアイテムであるのに対し、ファントム読み取りはバッチデータ全体に対するものです。(同時に書き込み、同時に読み取り)
3)データベーストランザクションレベル、繰り返し可能読み取りレベルがデフォルトで使用され、リストレベルは下から上に向かって低くなります。ビューレベル
select @@tx_isolation;
第4に、はるか遠くに、上記のSpringトランザクションとデータベーストランザクションの分離レベルを記述します。主な目的は、トランザクション間の転送関係を理解することです。これにより、Springは、制御時にトランザクションとトランザクション間の関係を使用して、ロールバックまたは効果を実現します。提出の。
5.注釈(マルチスレッドなど)を使用する方法がない場合は、手動の方法を使用してトランザクション管理を行う必要があります。これは、プログラムによるトランザクション管理です。
1)最初にアノテーションを追加します。これはSpringのjdbcフレームワークで提供されるトランザクション管理方法です。
@Autowired
private PlatformTransactionManager platformTransactionManager;
@Autowired
private TransactionDefinition transactionDefinition;
2)ソースコードを見てください(DataSourceTransactionManagerAutoConfiguration.class、TransactionTemplate.class)
@Bean
@ConditionalOnMissingBean({PlatformTransactionManager.class})
public DataSourceTransactionManager transactionManager(DataSourceProperties properties) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource);
if (this.transactionManagerCustomizers != null) {
this.transactionManagerCustomizers.customize(transactionManager);
}
return transactionManager;
}
注:興味がある場合は、DataSourceTransactionManagerの記述と原則について学ぶことができます。
@Bean
@ConditionalOnMissingBean
public TransactionTemplate transactionTemplate() {
return new TransactionTemplate(this.transactionManager);
}
ここでの処理を含むすべてのトランザクション伝播方法は、手動で処理する必要があることに注意してください。
3)書き方
TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
platformTransactionManager.commit(transactionStatus);
platformTransactionManager.rollback(transactionStatus);
説明:ここでトランザクションが開発された後、トランザクションステータスが返されます。このステータスは物事を記録し、トランザクションの管理を制御するために使用されます。もちろん、複数のトランザクション間の制御には人間による制御が必要です。
4)制御の程度の点でスプリング法の方が優れているため、プログラムによるトランザクション制御の量はあまり使用されません。トランザクションが必要なときにトランザクションに参加する方法がない場合はプログラムによる方法が多く使用され、その後手動で使用されます。トランザクションを制御する方法。
使用例:
1 在service内注入 这两个bean
@Autowired
private PlatformTransactionManager platformTransactionManager;
@Autowired
private TransactionDefinition transactionDefinition;
2在 service方法内创建TransactionStatus
TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
通过 platformTransactionManager.commit(transactionStatus); 提交事务
通过 platformTransactionManager.rollback(transactionStatus); 回滚事务
示例代码:
@Autowired
private PlatformTransactionManager platformTransactionManager;
@Autowired
private TransactionDefinition transactionDefinition;
public void b(){
TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
UserIntegralInfo info = new UserIntegralInfo();
info.setUserId(1L);
info.setPoint(1);
info.setOp("");
info.setCurrIntegral(1);
integralMapper.insert(info);
platformTransactionManager.commit(transactionStatus);
throw new RuntimeException();
}