みなさん、こんにちは。氷河です~~
日常業務において、Springのトランザクション管理機能を不適切に使用すると、Springトランザクションが有効にならないという問題が発生します。春の取引が有効にならないという問題は、転職の面接でよく聞かれる質問でもあります。
今日は、Springトランザクションが有効になるシナリオを整理しましょう。
注:コンテンツの一部は、 Glacier and Catが発行した「分散トランザクションの詳細な理解:原則と実践」という本から引用されています。
記事はGitHubとGiteeに含まれています:
GitHub:https://github.com/sunshinelyz/technology-binghe
Gitee:https://gitee.com/binghe001/technology-binghe
有効にならないSpringトランザクションの概要
つまり、次の図に示すように、Springトランザクションはいくつかの特定のシナリオで失敗します。
データベースはトランザクションをサポートしていません
Springトランザクションが有効になるための前提条件は、接続されたデータベースがトランザクションをサポートしていることです。基盤となるデータベースがトランザクションをサポートしていない場合、Springトランザクションは確実に失敗します。たとえば、使用されているデータベースがMySQLであり、MyISAMストレージエンジンが選択されている場合、Springのトランザクションは失敗します。
トランザクションメソッドはSpringによって管理されていません
トランザクションメソッドが配置されているクラスがSpringIOCコンテナにロードされていない場合、つまりトランザクションメソッドが配置されているクラスがSpringによって管理されていない場合、Springトランザクションは失敗します。例は次のとおりです。
public class ProductService {
@Autowired
private ProductDao productDao;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateProductStockCountById(Integer stockCount, Long id){
productDao.updateProductStockCountById(stockCount, id);
}
}
ProductServiceクラスには@Serviceアノテーションがなく、ProductのインスタンスがSpring IOCコンテナーにロードされないため、SpringでupdateProductStockCountById()メソッドのトランザクションが失敗します。
メソッドはパブリックによって変更されません
トランザクションが配置されているメソッドがpublicによって変更されていない場合、たとえば次のコードに示すように、Springのトランザクションは無効になります。
@Service
public class ProductService {
@Autowired
private ProductDao productDao;
@Transactional(propagation = Propagation.REQUIRES_NEW)
private void updateProductStockCountById(Integer stockCount, Long id){
productDao.updateProductStockCountById(stockCount, id);
}
}
ProductServiceは@Serviceアノテーションでマークされていますが、updateProductStockCountById()メソッドは@Transactional(propagation = Propagation.REQUIRES_NEW)アノテーションでマークされています。
ただし、updateProductStockCountById()メソッドは内部プライベートメソッド(privateで変更)であるため、現時点では、updateProductStockCountById()メソッドのトランザクションはSpringでは無効になります。
同じクラスのメソッド呼び出し
同じクラスの2つのメソッドがAとBの場合、トランザクションアノテーションはメソッドAに追加されず、@ TransactionalトランザクションアノテーションがメソッドBに追加され、メソッドAがメソッドBを呼び出すと、メソッドBのトランザクションは無効になります。たとえば、次のコードに示すように。
@Service
public class OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
public void submitOrder(){
//生成订单
Order order = new Order();
long number = Math.abs(new Random().nextInt(500));
order.setId(number);
order.setOrderNo("order_" + number);
orderDao.saveOrder(order);
//减库存
this.updateProductStockCountById(1, 1L);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateProductStockCountById(Integer stockCount, Long id){
productDao.updateProductStockCountById(stockCount, id);
}
}
submitOrder()メソッドとupdateProductStockCountById()メソッドはどちらもOrderServiceクラスにあります。submitOrder()メソッドはトランザクションアノテーションでマークされておらず、updateProductStockCountById()メソッドはトランザクションアノテーションでマークされています。submitOrder()メソッドはupdateProductStockCountByIdを呼び出します。 ()メソッド。現時点では、updateProductStockCountById()メソッドトランザクションはSpringで無効になっています。
トランザクションマネージャーが構成されていません
プロジェクトでSpringのトランザクションマネージャーが構成されていない場合、Springのトランザクション管理機能を使用しても、Springのトランザクションは有効になりません。
たとえば、次のコードはプロジェクトの構成クラスで構成されていません。
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
この時点で、Springのトランザクションは無効になります。
メソッドのトランザクション伝播タイプはトランザクションをサポートしていません
内部メソッドのトランザクション伝播タイプがトランザクションをサポートしない伝播タイプである場合、内部メソッドのトランザクションはSpringでは無効になります。
たとえば、次のコードに示すように。
@Service
public class OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
@Transactional(propagation = Propagation.REQUIRED)
public void submitOrder(){
//生成订单
Order order = new Order();
long number = Math.abs(new Random().nextInt(500));
order.setId(number);
order.setOrderNo("order_" + number);
orderDao.saveOrder(order);
//减库存
this.updateProductStockCountById(1, 1L);
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void updateProductStockCountById(Integer stockCount, Long id){
productDao.updateProductStockCountById(stockCount, id);
}
}
updateProductStockCountById()メソッドのトランザクション伝播タイプはNOT_SUPPORTEDであり、トランザクションをサポートしていないため、updateProductStockCountById()メソッドのトランザクションはSpringでは無効になります。
誤ってキャッチされた例外
以下に示すように、誤ってキャッチされた例外により、Springのトランザクションが失敗する可能性もあります。
@Service
public class OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
@Transactional(propagation = Propagation.REQUIRED)
public void submitOrder(){
//生成订单
Order order = new Order();
long number = Math.abs(new Random().nextInt(500));
order.setId(number);
order.setOrderNo("order_" + number);
orderDao.saveOrder(order);
//减库存
this.updateProductStockCountById(1, 1L);
}
@Transactional(propagation = Propagation.REQUIRED)
public void updateProductStockCountById(Integer stockCount, Long id){
try{
productDao.updateProductStockCountById(stockCount, id);
int i = 1 / 0;
}catch(Exception e){
logger.error("扣减库存异常:", e.getMesaage());
}
}
}
updateProductStockCountById()メソッドでtry-catchコードブロックを使用して例外をキャッチします。updateProductStockCountById()メソッド内で例外がスローされた場合でも、catchコードブロックによってキャッチされます。このとき、 updateProductStockCountById()メソッドは、ロールバックを返さずにコミットされ、submitOrder()メソッドのトランザクションはコミットされますが、ロールバックされないため、Springトランザクションのロールバックが失敗します。
間違った注釈例外タイプ
@Transactionalアノテーションで間違った例外タイプがマークされている場合、Springトランザクションのロールバックは無効になります。例は次のとおりです。
@Transactional(propagation = Propagation.REQUIRED)
public void updateProductStockCountById(Integer stockCount, Long id){
try{
productDao.updateProductStockCountById(stockCount, id);
}catch(Exception e){
logger.error("扣减库存异常:", e.getMesaage());
throw new Exception("扣减库存异常");
}
}
例外はupdateProductStockCountById()メソッドでキャッチされ、例外タイプの例外が例外でスローされます。この時点で、updateProductStockCountById()メソッドのトランザクションロールバックは無効になります。
なぜ失敗するのですか?これは、Springのデフォルトのロールバックのトランザクション例外タイプがRuntimeExceptionであり、上記のコードが例外例外をスローするためです。
デフォルトでは、例外例外はSpringトランザクションでキャッチできないため、updateProductStockCountById()メソッドでのトランザクションのロールバックは無効になります。
この時点で、次に示すように、updateProductStockCountById()メソッドでマークされたトランザクション例外タイプを手動で指定できます。
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
ここで、Springトランザクションアノテーション@TransactionalのrollbackFor属性は、Throwable例外クラスとそのサブクラスを指定できることに注意してください。
さて、今日はここでやめましょう、私は氷河です、また会いましょう~~
最後に書く
大きな工場に参入したい、昇進や昇給をしたい、または現在の仕事について混乱している場合は、私にメッセージを送って連絡することができます。私の経験のいくつかがあなたに役立つことを願っています~~
推奨読書:
- 「実践は真の知識をもたらします。ネットワーク全体で最強のseckillシステムのアーキテクチャを解読することで、すべてのseckillがseckillであるとは限りません。!》
- 「ゼロから数億人のユーザーまで、MySQLデータベースを段階的に最適化するにはどうすればよいですか?(おすすめコレクション)》
- 「私はマルチスレッドを使用して、10億レベルのトラフィックeコマースビジネスの下で大規模なデータ校正システムをさらに最適化し、パフォーマンスが200%向上しました。!(全体が乾いているので、集めることをお勧めします)》
- 「私はマルチスレッドを使用して、10億レベルのトラフィックeコマースビジネスの下で大規模なデータ校正システムを最適化しました。パフォーマンスは直接200%向上しました。!(全体が乾いているので、集めることをお勧めします)》
- 「同時プログラミングに最適な学習ルートを10枚の写真でまとめました。!(おすすめコレクション)》
- 「同時実行性の高いシナリオでは、読み取り/書き込みロックよりも高速なロックです。これを読んだ後、私は完全に確信しています。!(おすすめコレクション)》
- 「ネットワーク全体の最も完全なパフォーマンス最適化の要約!!(氷河吐血アレンジメント、推奨コレクション)》
- 「MyBatisを3日間プレイした後は、お気軽にお問い合わせください。!(氷河吐血アレンジメント、推奨コレクション)》
- 「働き始めたばかりの人へのアドバイス:大きな工場に入るには、これらの並行プログラミングの知識を習得する必要があります。完全な学習ルート!!(おすすめコレクション)》
- 「働き始めたばかりのジュニアやジュニアへのアドバイス:大きな工場に入るには、これらのコアスキルを習得する必要があります!完全な学習ルート!!(おすすめコレクション)》
- 「仕事を始めたばかりの人へのアドバイス:これらのコンピューターとオペレーティングシステムの基本を早く理解すればするほどよいでしょう。10,000文字の長さのテキストはトップすぎます!!(おすすめコレクション)》
- 「私は3日間ですべての年齢層に適した全国レベルのゲームを開発し、音楽の再生をサポートし、完全なソースコードとコメント(推奨コレクション)を開きます!!》
- 「私はネットワーク全体で最もハードコアな同時実行性プログラミングの作者であり、CSDNで最も注目に値するブロガーです。同意しますか?(おすすめコレクション)》
- 「卒業から5年後、月給3,000から年俸100万まで、どのようなコアスキルを身につけましたか?(おすすめコレクション)》
- 「隣の女の子のWifiをハッキングして見つけました。。。(実際の戦闘乾物の全工程、収集することをお勧めします) "
- 「『パンダバーニングお香』を軽く試さないでください、いや、後悔します!》
- 「墓掃除の日はこっそりと「パンダお香」を訓練し、私のコンピューターはパンダに「専用」になりました!》
- 「Java8の新機能でいっぱいの73万語、あなたがそれを読むことができるとは思わない!(おすすめコレクション)》
- 「営業時間のピーク時にサーバーのプラグを抜くのはどうですか?》
- 「ネットワーク全体で最も完全なLinuxコマンドの要約!!(歴史上最も完全な、推奨コレクション) "
- 「Pythonでツールを作成し、MySQLを完全にクラックしました。!(おすすめコレクション)》
- SimpleDateFormatクラスがスレッドセーフではないのはなぜですか?(6つのソリューション、推奨コレクション) "
- 「MySQL8のこれらの3つの新しいインデックスは、MySQLを直接離陸させました、あなたはそれさえ知らないのです!!(おすすめコレクション)》
- 「Springのソースコードを完成させた後、この分散キャッシュフレームワークをオープンソース化しました。!(おすすめコレクション)》
- 「1億レベルのトラフィックの高い同時スパイクシステムの製品は、使用されているJDK同期コンテナにこれらの2つの巨大なピットがあるという理由だけで、「売られ過ぎ」です。!(ピットを踏んだ記録、収集をお勧めします)」
- 「作業を始めたばかりの人にアドバイスしてください。並行プログラミングを上手に学びたいのであれば、これらの並行コンテナの落とし穴に注意を払う必要があります。!(おすすめコレクション)》
- 「会社のレポートツールは使いにくいです。3日でExcelツールを手に入れました。オペレーションレディはとても使いやすいと言って、今ではオープンソースになっています!!(おすすめコレクション)》
- 「働き始めたばかりの人へのアドバイス:大きな工場に参入したいのなら、並行プログラミングのこれらのコアスキルはあなたが習得しなければならないものです!!(おすすめコレクション)》
- 「アリインタビュアー:同時実行性とトラフィックの多いスパイクシステムは、在庫の売られ過ぎの問題をどのように正しく解決しますか?(おすすめコレクション)》
- 「5つのデータ型と使用シナリオの概要を再確認してください!!(完全な実際の戦闘ケースを含む、収集することをお勧めします)》
さて、今日ここで立ち止まって、友達、いいね、お気に入り、コメント、そしてワンクリックで歩き始めましょう、私は氷河です、次の号でお会いしましょう~~