0

トランザクションがどのように機能し、すべてが期待どおりに機能するかは理解していますが、トランザクションをコミットまたはロールバックするために接続にアクセスする方法が好きではありません。

同じシングルトン接続オブジェクトにアクセスできる 3 つのサービス クラスがあります。これら 3 つのことを 1 つのトランザクションでラップしたいので、次のようにします。

try {
  $service1 = new ServiceOne;
  $service2 = new ServiceTwo;
  $service3 = new ServiceThree;

  $service1->insertRec1($data);
  $service2->deleteRec2($data);
  $service3->updateRec3($data);

  $service1->getSingletonConnection()->commit();
}
catch(Exception $ex) {
  $service1->getSingletonConnection()->rollback();
}

getSingletonConnection によって返される接続オブジェクトは、oci8 接続の単なるラッパーであり、コミットはoci_commit; ロールバックはoci_rollback

前述したように、これはすべて同じ接続にアクセスしているため機能しますが、任意のサービス オブジェクトを介して接続にアクセスするのは間違っていると感じます。また、私のアプリでは 2 つの異なるデータベースが使用されているため、正しいデータベースを取得してコミットする必要がありますが、それを回避する方法があるかどうかはわかりません。

トランザクションを処理するためのより良い方法はありますか?

4

2 に答える 2

2

任意のサービス オブジェクトを介して接続にアクセスするのは間違っていると感じます。

私はあなたに100%同意します。

各サービスがデータベース トランザクションの一部のみを構成している場合、使用するデータベース セッションの決定をサービスが直接担当することはできないように思われます。トランザクションを定義するコードのレベルで接続を選択して管理する必要があります。

したがって、現在のコードは次のように変更されます。

try {
  $conn = getSingletonConnection();
  $service1 = new ServiceOne($conn);
  $service2 = new ServiceTwo($conn);
  $service3 = new ServiceThree($conn);

  $service1->insertRec1($data);
  $service2->deleteRec2($data);
  $service3->updateRec3($data);

  $conn->commit();
}
catch(Exception $ex) {
  $conn->rollback();
}

これは、使用する接続を決定する場所が 1 つしかなく、トランザクションを終了するまでその接続への直接参照を保持するため、2 つのデータベースの問題への対処が簡単になるようです。

シングルトン接続から接続プールに拡張したい場合、3 つのサービス呼び出しすべてが同じ接続を使用することを保証するには、これが唯一の方法だと思います。

于 2011-03-08T14:57:38.570 に答える
1

単一の接続に本質的に問題はありません。複数の接続がある場合、それぞれが独立したトランザクションを実行します。基本的に 2 つのオプションがあります。

  • 3 つのサービスのそれぞれに対して現在の単一の接続オブジェクトを維持する
  • サービスごとに個別の接続を (関連するオーバーヘッドとともに) 維持し、個々の接続を個別にコミット/ロールバックします (ACID の一貫性を保証できないため、特に安全ではありません)。

接続先の 2 つの別個のデータベース インスタンスを回避する方法として、db リンクを使用して、単一のデータベースにのみ接続するようにします。

于 2011-03-07T15:15:14.813 に答える