Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (日本語) » Ultra Light - M-Business Anywhere プログラミング » Ultra Light for M-Business Anywhere 開発の概要

 

M-Business Anywhere アプリケーションにおける永続的な名前

HTML では、制御が新しいページに移ると、古いページで割り付けられていた JavaScript オブジェクトへのすべてのハンドルが失われます。たとえば main.html には、M-Business Anywhere データベース接続オブジェクトがあります。

conn = dbMgr.openConnection("...");

main.html のリンクをクリックして insert.html などの別のページに移動すると、insert.html ではオブジェクト "conn" が見つかりません。この接続オブジェクトを取得し直すには、dbMgr.openConnection("...") をもう一度呼び出す必要がある可能性があります。ただし、接続オブジェクトはメモリ内にまだ存在するため、そのようにする必要はありません。そのオブジェクトに対する JavaScript ハンドルが失われたにすぎません。

DataManager、Connection、ULTable、PreparedStatement、ResultSet に対するすべての M-Business Anywhere API 呼び出しに persistName 引数が存在するのはこのためです。たとえば、M-Business Anywhere ランタイムが Ultra Light 接続オブジェクトに対する JavaScript からの呼び出しを受け取ると、M-Business Anywhere は、同じ persistName を持つ接続オブジェクトがメモリ内に存在するかどうかを最初にチェックします。一致するオブジェクトが見つかると、ランタイムはその接続オブジェクトを返します。見つからない場合は、M-Business Anywhere は通常の手順に移り、新しい Ultra Light データベース接続を作成して返します。

永続的な名前の使用

M-Business Anywhere オブジェクト間の階層には 2 種類あります。どちらの場合も、次のように DatabaseManager と Connection から始まります。

これらの M-Business Anywhere オブジェクトを永続的な名前で取得するには、最上位レベルのオブジェクトを永続的な名前で取得し、次に必要な M-Business Anywhere オブジェクトに至るまで、階層ツリーで上位レベルにあるすべての M-Business Anywhere オブジェクトを取得する必要があります。

たとえば、既存の ULTable オブジェクトを insert.html から取得する場合は、main.html で dbMgr、conn、table の各オブジェクトに永続的な名前を付けてから、insert.html で永続的な名前を使用してそれらすべてを取得します。

main.html のコード・セグメント:

var dbMgr = CreateObject( "iAnywhere.UltraLite.DatabaseManager.simple" ); 
// "simple" is the persistent name here. A real database manager object is allocated

var conn = dbMgr.openConnection( "CON=simple_con;..." ); 
// "simple_con" is the persistent name here. A real database connection is made.

var custTable = conn.getTable( "ULCustomer", "simpleCustTable" ); 
// a real table is allocated

insert.html のコード・セグメント:

var dbMgr = CreateObject( "iAnywhere.UltraLite.DatabaseManager.simple" ); 
// "simple" is the persistent name here. 
// The allocated database manager object from main.html is returned

var conn = dbMgr.openConnection( "CON=simple_con;..." ); 
// "simple_con" is the persistent name here. 
// The existing connection object from memory is returned.

var custTable = conn.getTable( "ULCustomer", "simpleCustTable" ); 
// the existing table object is returned.

var newTable = conn.getTable( "ULOrder", "simpleOrderTable" ); 
// since there is no order table from main.html, 
// it does not exist in memory. A real order table object is allocated.
永続的な名前の適切な使用

共通で使用されるコードは、JavaScript ファイルに配置します。M-Business Anywhere アプリケーションのほとんどの HTML ページでは、DatabaseManager オブジェクト、Connection オブジェクト、主要な ULTable オブジェクトを参照する必要があるため、これらのオブジェクトを作成する (または、永続的な名前でこれらのオブジェクトを取得する) コードを共通の JavaScript ファイルに配置し、オブジェクトを使用する HTML ページの最初で、そのファイルをインクルードする方が便利です。M-Business Anywhere サンプル・プログラムの "Simple" と "CustDB" の両方で、その方法が示されています。

別のページからオブジェクトを使用する予定がない場合は、そのオブジェクトを閉じます。M-Business Anywhere アプリケーションに HTML ページが 1 つしかない場合は、永続的な名前を使用する必要はありません。永続的な名前の引数を NULL に設定することもできます。一方、各 HTML ページで PreparedStatement オブジェクトと ResultSet オブジェクトが多数開かれている場合は、開発者は、これらのオブジェクトをメモリ内に保持することで永続名を使用して別の HTML ページから簡単に取得できるという便利さと、これらのオブジェクトが常に存在するために生じるメモリの浪費とのバランスを取る必要があります。たとえば、5 個の PreparedStatement オブジェクトと 10 個の ResultSet オブジェクトが main.html で作成されたとします。これらはメモリを大量に占有しています。アプリケーションで insert.html に移動する場合、これらのオブジェクトのうち永続的な名前で参照する必要があるのが一部だけであれば、必要ではなくなったオブジェクトによってメモリが浪費されています。insert.html で新しく PreparedStatement オブジェクトと ResultSet オブジェクトを作成しようとすると、メモリが不足する可能性があります。これを解決するには、insert.html でこれらの PreparedStatement オブジェクトや ResultSet オブジェクトを必要としないことがわかっている場合は、main.html の最後に明示的にオブジェクトを閉じるようにします。

各 M-Business Anywhere オブジェクトの状態は、永続的な名前で取得される場合も保持されます。1 ページ目からの永続的な ULTable オブジェクトが存在する状態で、2 ページ目から同じ永続名を使用して openTable メソッドを呼び出すと、1 ページ目での状態と同じ状態でその ULtable オブジェクトを取得します。1 ページ目から移動するときにカーソルがテーブルで n 番目のローにある場合、2 ページ目でこのオブジェクトを取得したときも、カーソルは n 番目のローにあるままです。「最初のローの前」にカーソルが来ることはありません。

ResultSet で永続的な名前を使用する場合は注意してください。PreparedStatement にプレースホルダがある場合は、ResultSet に永続名を付けるかどうかについて慎重に考慮する必要があります。たとえば、main.html に次のコードがあるとします。

var OrderStmt = Connection.prepareStatement(
"SELECT order_id, disc, quant FROM ULOrder WHERE order_id = ?", 
"order_query_stmt" );

OrderStmt.setInt(1, 5000);

var OrderResultSet = OrderStmt.executeQuery( "order_query_result" );

insert.html で同じ ResultSet オブジェクトが必要な場合は、次のようにする必要があります。

var OrderStmt = Connection.prepareStatement(
"SELECT order_id, disc, quant FROM ULOrder WHERE order_id = ?", 
"order_query_stmt" );

//OrderStmt.setInt(1, 5000); // no need to do this since both the OrderStmt and 
OrderResultSet are retrieve from "cache" without any SQL statement being 
actually executed

var OrderResultSet = OrderStmt.executeQuery( "order_query_result" );

この OrderResultSet オブジェクトには、"order_id" が 5000 に設定された場合と同じ結果が格納されます。

しかし、別の状況も考えられます。Order テーブルで同じクエリを実行するために、同じ PreparedStatement が必要だとします。ただし、クエリでは 5000 以外の order_id を使用します。この場合、永続的な名前を PreparedStatement に割り当てることはできますが、ResultSet には永続的な名前は必要ありません。この状況では order_id が異なるため、前の例とは違う結果セットになります。main.html では、次のような同様のコードになります。

var OrderStmt = Connection.prepareStatement(
"SELECT order_id, disc, quant FROM ULOrder WHERE order_id = ?", 
"order_query_stmt" ); // with persistent name

OrderStmt.setInt(1, 5000);

var OrderResultSet = OrderStmt.executeQuery( null ); // notice here, no persistent name

insert.html では、次のようにして新しい ResultSet を取得します。

var OrderStmt = Connection.prepareStatement(
"SELECT order_id, disc, quant FROM ULOrder WHERE order_id = ?", 
"order_query_stmt" ); // get the prepared statement from memory with persistent name

OrderStmt.setInt(1, 6000); // set a different place holder value

var OrderResultSet = OrderStmt.executeQuery( null ); // a real query is executed 
here!

この例では、プレースホルダの値が異なるか、Order テーブルで返される結果セットが異なると予期される他の操作が実行されるため、executeQuery の呼び出し時に ResultSet に永続的な名前を使用する必要がありません。