TTCmd、TTConnectionおよびTTConnectionPoolの使用

この項では、適切に利用されていて各種アプリケーションに簡単に適応できるようにTTClassesを使用するためのアプローチについて説明します。

リアルタイム・アプリケーションでは、最適なパフォーマンスを得るために、準備済のSQL文を使用する必要があります。アプリケーションで使用されるすべてのSQL文について、文ごとに個別のTTCmdオブジェクトを使用して、アプリケーションの開始時に準備するのが理想的です。ODBCでは(したがってTTClassesでも)、文が特定の接続にバインドされるため、アプリケーションで使用される文の完全なセットが、データベースとのすべての接続に関連付けられるということがよく起こります。

これを実現する簡単な方法は、TTConnectionから導出されるアプリケーション固有のクラスを開発することです。たとえば、XYZという名前のアプリケーションには、XYZConnectionというクラスを作成できます。XYZConnectionクラスには、アプリケーションで使用する準備済のSQL文を表すプライベートTTCmdメンバーを含め、これでは、これらのプライベートTTCmdメンバーを介してアプリケーション固有のデータベース機能を実装する新しいパブリック・メソッドを提供します。

TTCmdオブジェクトは、使用前にSQL文(SELECTINSERTUPDATEまたはDELETE)と関連付ける必要があります。関連付けはPrepare()メソッドを使用して行います。これによってSQL文がコンパイルおよび最適化され、SQL文が効率的に実行されるようになります。Prepare()メソッドは文を準備するだけで、文を実行しない点に注意してください。

通常、TimesTenでは、性能の向上のために文はパラメータ化されます。次のようなSQL文を考えてみます。

SELECT col1 FROM table1 WHERE C = 10;
SELECT col1 FROM table1 WHERE C = 11;

これよりも、パラメータ化された1つの文を準備し、それを複数回実行した方がより効率的です。

SELECT col1 FROM table1 WHERE C = ?;

「?」の値は、TTCmd::setParam()メソッドを使用して実行時に指定します。

ODBCを直接使用する場合と違い、列またはパラメータを明示的にSQL文にバインドする必要はありません。TTCmdは、準備する際にすべての必要な列を自動的に定義しバインドします。パラメータは実行時にバインドされます。

準備は比較的負荷の高い操作であることに注意してください。アプリケーションは、(TTConnection::Connect()を使用して)TimesTenへの接続を確立する際に、その接続に関連付けられたすべてのTTCmdオブジェクトを準備する必要があります。アプリケーションのこのメイン実行ループの前に、すべてのSQL文を準備してください。

TTClassesメソッドでエラーまたは警告が発生すると、TTStatusオブジェクトが例外としてスローされます。この例外はアプリケーション側で捕捉して正しく処理する必要があります。TimesTen Classicクイック・スタートのサンプル・アプリケーションには、この実施方法が示されています。TimesTenクイック・スタートおよびサンプル・アプリケーションについてを参照してください。

ノート:

必要な特定のgetまたはsetメソッドがTTConnectionまたはTTCmdにない場合は、TTConnection::getHdbc()およびTTCmd::getHandle()メソッドを使用して、基礎となるODBC接続ハンドルおよび文ハンドルに直接アクセスできます。同様に、ODBC環境ハンドルにはTTGlobal::sqlhenv()メソッドでアクセスします。

TTConnectionから継承されるクラスの例を次に示します。

class XYZConnection : public TTConnection {
private:
  TTCmd updateData;
  TTCmd insertData;
  TTCmd queryData;

public:
  XYZConnection();
  ~XYZConnection();
  virtual void Connect (const char* connStr, const char* user, const char* pwd);
  void updateUser ();
  void addUser (char* nameP);
  void queryUser (const char* nameP, int* valueP);
};

この例では、XYZConnectionオブジェクトがTimesTenへの接続であり、アプリケーション固有の3つの操作(addUser()updateUser()およびqueryUser())の実行に使用できるようになっています。これらの操作はXYZアプリケーションに固有です。これらの3つのメソッドの実装では、アプリケーションのデータベース操作を実装するために、updateDatainsertDataおよびqueryData TTCmdオブジェクトを使用できます。

アプリケーションのSQL文を準備するために、XYZConnectionクラスは、TTConnection基本クラスから提供されるConnect()メソッドをオーバーロードします。XYZConnection::Connect()メソッドは、データベース接続を確立するために、基本クラスのConnect()メソッドをコールし、さらに、TTCmdオブジェクトごとにPrepare()メソッドもコールして、後で使用するSQL文を準備します。

次の例は、XYZConnection::Connect()メソッドの実装を示しています。

void
XYZConnection::Connect(const char* connStr, const char* user, const char* pwd)
{
  try {
    TTConnection::Connect(connStr, user, pwd);
    updateData.Prepare(this, "update mydata v set foo = ? where bar = ?");
    insertData.Prepare(this, "insert into mydata values(?,0)");
    queryData.Prepare(this, "select i from mydata where name = ?");
  }
  catch (TTStatus st) {
    cerr << "Error in XYZConnection::Connect: " << st << endl;
  }
  return;
}

このConnect()メソッドにより、XYZConnectionオブジェクトとそのアプリケーション固有のメソッドが完全に動作可能になります。

この方法は、TTConnectionPoolクラスの設計でも非常に有効です。アプリケーションは、XYZConnection型のオブジェクトを多数作成し、それらをTTConnectionPoolオブジェクトに追加できます。TTConnectionPool::ConnectAll()がコールされると、アプリケーションはプール内のデータベースへのすべての接続を接続し、すべてのSQL文を準備します。切断するには、TTConnectionPool::DisconnectAll()を使用します。

このアプリケーションの設計により、データベースへのアクセスがアプリケーションのビジネス・ロジックから簡単に分離できます。XYZConnectionクラスのみに、データベース固有のコードが含まれるようになります。

このアプリケーション設計の例は、TimesTen Classicクイック・スタートで提供されるいくつかのTTClassesのサンプル・アプリケーションで確認できます。TimesTenクイック・スタートおよびサンプル・アプリケーションについてを参照してください。

他の構成が可能なことに注意してください。アプリケーションで使用されるSQL文が、アプリケーション自体にハードコードされるのではなく、データベース内の表にリストされるよう、このスキームをさらに拡張したユーザーもいます。このようにすれば、アプリケーションの変更ではなくデータベースの変更によって、データベースの機能の変更を実装できます。

次の例は、XYZConnection::Disconnect()メソッドの実装を示しています。

void
XYZConnection::Disconnect()
{
  updateData.Drop();
  insertData.Drop();
  queryData.Drop();
 
  TTConnection::Disconnect();
}

TTCmdの使用方法TTConnectionの使用方法およびTTConnectionPoolの使用方法も参照してください。