春のトランザクションサービスアナログ

    総務は、このような操作のいずれか、すべてが成功するか、すべてが失敗のセットのデータベースなどの操作、一連の抽象的な記述です。
    トランザクションは、4つの特徴があります。
        アトミック(不可分)、一貫性(整合性)、分離(単離)、耐久性(永続的)
    、(MySQLのMyISAMのエンジンがトランザクションをサポートしていない)トランザクションのための春のサポートは非​​常に強力ですが、本質的には、効果へのトランザクションは、基礎となるデータベースサポートするかどうかに依存しているかどうか
同時に、トランザクションは、同じ接続上で複数の操作が必要です。デモ春のトランザクション基礎となる実装、次の手書きの分析。
 
  • エンジニアリング構造
        
 
  • 接続部
           スプリングと、接続管を介してデータソースデータベースの動作を得るために必要なデータソースデータソースの複数。
            
インポートのjava.sql.Connection;
輸入ます。java.sql.SQLException;
輸入java.util.HashMapを;
輸入java.util.Map;
インポートするjavax.sql.DataSource;
パブリッククラスConnectionHolder {
     //地図データは、地図ソース接続ラインに格納されています
     プライベート地図<データソース、接続>マップ=新しいHashMapの<データソース、接続>();
     //接続応じてデータソースを取得します
     パブリック接続getConnectionByDataSource(データソースデータソース)はSQLExceptionが{スロー
          接続の接続= map.get(データソース)。
          IF(接続== NULL || connection.isClosed()){
              接続= datasource.getConnection()。
              map.put(データソース、接続)。
          }
          接続を返します。
     }
}
   
マルチスレッドの場合ConnectionHolderは、マップは、スレッドセーフではないが、近いリンクの場合に別のスレッドを同時に使用することができます。
    もう一つのアイデアは、スレッドセーフのConcurrentHashMapを使用することです。しかし、私たちは本当に実行する必要があり、次のスレッド、1つのトランザクションで複数の操作で接続を取得することであることを確認のConcurrentHashMapを保証するものではありません使用することです
この問題は。
    したがって、使用のThreadLocalの種類を考慮して、ThreadLocalのタイプは、共有変数をスレッドであるグローバル変数スレッドです。そしてThreadLocalのは、複数のスレッドの場合には、各スレッドのコピーを作成します、にThreadLocal変数のスレッド操作にのみ、このスレッドでのコピーに影響を与えます。
    
インポートのjava.sql.Connection;
輸入ます。java.sql.SQLException;
インポートするjavax.sql.DataSource;
 
パブリッククラスSingleThreadConnectionHolder {
    // ThreadLocalのスレッド共有変数パッケージマップ
     プライベート静的にThreadLocal <ConnectionHolder> THREADLOCAL =新しいのThreadLocal <ConnectionHolder>();
     プライベート静的ConnectionHolder getConnectionHolder(){
          ConnectionHolder connectionHolder = threadLocal.get()。
          IF(connectionHolder == NULL){
              connectionHolder =新しいConnectionHolder();
              threadLocal.set(connectionHolder)。
          }
          connectionHolderを返します。
     }
     パブリック静的接続のgetConnection(データソースデータソース)はSQLExceptionが{スロー
          戻るgetConnectionHolder()getConnectionByDataSource(データソース)。
     }
}
        カプセル化によってThreadLocalの後、スレッドは、DataSource取得した接続がユニークである保証することができます。
 
  • 一部の管理
 
        トランザクション制御のための新しいTransactionManage、
インポートのjava.sql.Connection;
輸入ます。java.sql.SQLException;
インポートするjavax.sql.DataSource;
輸入resource.connection.SingleThreadConnectionHolder。
パブリッククラスのTransactionManager {
     プライベートデータソースのdataSource。
     公共のTransactionManager(データソースデータソース){
          // TODO自動生成されたコンストラクタのスタブ
          this.dataSource =のdataSource;
     }
     プライベート接続のgetConnection()、SQLExceptionをスローします{
          SingleThreadConnectionHolder.getConnection(データソース)を返します。
     }
     //オープン情勢
     公共ボイド開始()はSQLExceptionをスローします{
          接続の接続=のgetConnection();
          Connection.setAutoCommit(偽);
     }
     //トランザクションをロールバック
     公共ボイドロールバック(){
          接続の接続= NULL;
          {試します
              接続=のgetConnection();
              connection.rollback();
          }キャッチ(のSQLException e)の{
              e.printStackTrace();
          }
     }
     //トランザクションを閉じます
     公共ボイド近い()は、SQLExceptionをスローします{
          接続の接続=のgetConnection();
          connection.commit();
          Connection.setAutoCommit(偽);
          connection.close();
     }
}
 
  • UserAcountDao、UserOrderDaoを含むデータベース・リンクを操作するためのDAO層、
        ユーザーが操作ダオを購入します
インポートのjava.sql.Connection;
輸入ます。java.sql.SQLException;
インポートするjavax.sql.DataSource;
輸入resource.connection.SingleThreadConnectionHolder。
パブリッククラスUserAcountDao {
     プライベートデータソースのdataSource。
     公共UserAcountDao(データソースデータソース){
          this.dataSource =のdataSource;
     }
     
     ます。public void買い()はSQLExceptionをスローします{
          接続の接続= SingleThreadConnectionHolder.getConnection(データソース)。
          //事業運営
          // ....
          System.out.println( "スレッドを購入する現在のユーザー:"。+にThread.currentThread()のgetName()+
                   "パイプ(ハッシュコード)を使用してください:" + connection.hashCode());
     }
}
 
    注文操作のユーザーダオ
インポートのjava.sql.Connection;
輸入ます。java.sql.SQLException;
インポートするjavax.sql.DataSource;
輸入resource.connection.SingleThreadConnectionHolder。
パブリッククラスUserOrderDao {
     プライベートデータソースのdataSource。
     公共UserOrderDao(データソースデータソース){
          this.dataSource =のdataSource;
     }
     
     公共ボイドの順序()はSQLExceptionをスロー{
          接続の接続= SingleThreadConnectionHolder.getConnection(データソース)。
          //事業運営
          // ....
          System.out.println( "現在の顧客の注文のスレッド:" +にThread.currentThread()のgetName()+。
                   "使用管理(ハッシュコード):" + connection.hashCode());
     }
}
 
  • サービスレベル、ユーザーの業務運営
 
インポートするjavax.sql.DataSource;
輸入resource.dao.UserAcountDao。
輸入resource.dao.UserOrderDao。
輸入resource.manage.TransactionManager。
パブリッククラスUserServiceの{
     プライベートUserAcountDao userAcountDao。
     プライベートUserOrderDao userOrderDao。
     民間のTransactionManagerのTransactionManager。
 
     公共UserServiceの(データソースデータソース){
          userAcountDao =新しいUserAcountDao(データソース);
          userOrderDao =新しいUserOrderDao(データソース);
          トランザクションマネージャー=新しいトランザクションマネージャー(データソース);
     }
     公共ボイドアクション(){
          {試します
              //購入、次のシングルの操作を行います
              transactionManager.start();
              userAcountDao.buy();
              userOrderDao.order();
              transactionManager.close();
          }キャッチ(例外e){
              //例外が発生し、トランザクションはロールバックされます
              e.printStackTrace();
              transactionManager.rollback();
          }
     }
}
         
  • 試験試験手順
輸入resource.service.UserService。
パブリッククラスTestTransaction {
     public static final文字列jdbcDriver = "はcom.mysql.jdbc.Driver"。
     public static final文字列JDBCURL = "はjdbc: mysqlの:// localhostを:3306 / my_web useSslオプション= falseの? "。
     public static final文字列jdbcUsername = "******"; // MySQLユーザ名
     public static final文字列jdbcPassword = "******"; //密码
     
     パブリック静的無効メイン(文字列[] args){
          BasicDataSourceのBasicDataSource =新しいのBasicDataSource();
          basicDataSource.setDriverClassName(jdbcDriver)。
          basicDataSource.setUsername(jdbcUsername)。
          basicDataSource.setPassword(jdbcPassword)。
          basicDataSource.setUrl(JDBCURL)。
          最終UserServiceのUserServiceの=新しいUserServiceの(のBasicDataSource)。
 
          //シミュレートされたユーザーの同時要求
          {(; iが10 <I ++はiが0 = INT)のために
              新しいスレッド((Runnableを)() - > {userService.action();}))(開始。
          }
          
          {試します
              Thread.sleep(10000);
          }キャッチ(InterruptedExceptionある電子){
              e.printStackTrace();
          }
     }
}
 
       ユーザ同時リクエスト、10件のスレッドの合計をシミュレートする手順を試験することによって、各スレッドは、DAO層データ操作を呼び出します。次のように操作結果があります
 
 
スレッドを購入する現在のユーザー:1671328438:スレッド-10は、パイプ(ハッシュコード)を使用します
注文現在のユーザスレッド:スレッド10、パイプ(ハッシュコード)を使用:1671328438
スレッドを購入する現在のユーザー:1172249069:スレッド-5は、パイプ(ハッシュコード)を使用します
注文現在のユーザスレッド:スレッド5、パイプ(ハッシュコード)を使用:1172249069
スレッドを購入する現在のユーザー:スレッド-1、パイプ(ハッシュコード)を使用して:863698743
注文現在のユーザスレッド:スレッド1、パイプ(ハッシュコード)を使用しては:863698743
スレッドを購入する現在のユーザー:スレッド-7、パイプ(ハッシュコード)を使用した:1206124853
注文現在のユーザスレッド:スレッド-7、パイプ(ハッシュコード)を使用しては:1206124853
スレッドを購入する現在のユーザー:1861628772:スレッド-2は、パイプ(ハッシュコード)を使用します
スレッドを購入する現在のユーザー:スレッド-6、パイプ(ハッシュコード)を使用した:1394656535
注文現在のユーザスレッド:スレッド2、パイプ(ハッシュコード)を使用:1861628772
注文現在のユーザスレッド:スレッド6、パイプ(ハッシュコード)を使用しては:1394656535
スレッドを購入する現在のユーザー:スレッド-8、パイプ(ハッシュコード)を使用した:1883267477
注文現在のユーザスレッド:スレッド8、パイプ(ハッシュコード)を使用しては:1883267477
スレッドを購入する現在のユーザー:1475410105:スレッド-9は、パイプ(ハッシュコード)を使用します
注文現在のユーザスレッド:スレッド9、パイプ(ハッシュコード)を使用:1475410105
スレッドを購入する現在のユーザー:スレッド-3、パイプ(ハッシュコード)を使用した:1472283137
注文現在のユーザスレッド:スレッド3、パイプ(ハッシュコード)を使用しては:1472283137
スレッドを購入する現在のユーザー:スレッド-4、パイプ(ハッシュコード)を使用して:678585609
注文現在のユーザスレッド:スレッド4、パイプ(ハッシュコード)を使用しては:678585609
 
結果を見ることができ、同じスレッドが接続管を取得する複数のデータソースの存在、同じデータソース同じスレッドダクトが同じで取得した場合、同じです。
 
 
 
         

おすすめ

転載: www.cnblogs.com/ytcs8121/p/11331941.html