この章では、開発サイクル全般で最も一般的に使用される基本的なTopLink問合せAPIのコールについて説明します。
詳細は、「詳細問合せAPIの使用」を参照してください。
この項では例をあげ、次のセッション問合せメソッドの使用方法を説明します。
注意: すべてのデータソース操作は作業ユニットを使用して実行することをお薦めします。これがトランザクション、同時実行性および参照制約を管理する最も効率のよい方法です。詳細は、「TopLinkトランザクションの概要」を参照してください。 |
詳細は、「セッション問合せ」を参照してください。
セッション問合せAPIを使用すると、次の読取り操作を実行できます。
readObject
メソッドは、データベースからシングル・オブジェクトを取得します。アプリケーションでは、読取り対象のオブジェクトのクラスを指定する必要があります。基準に一致するオブジェクトがない場合は、null値が返されます。
たとえば、基本的な読取り操作は次のようになります。
session.readObject(MyDomainObject.class);
この例では、MyDomainObject
に使用される表で見つかったMyDomainObject
の最初のインスタンスを返します。TopLinkは、特定のオブジェクト用の問合せパラメータを指定するためのExpression
クラスを提供します。
主キーを使用して特定のシングル・オブジェクトを検索する場合、readAllObjects
メソッドよりもreadObject
メソッドの方が効率的です。これは、readObject
がデータベースにアクセスせずにキャッシュ内でインスタンスを見つけられるためです。readAllObjects
メソッドでは基準に一致するオブジェクトの数がわからないため、一致するオブジェクトがキャッシュ内で見つかったとしても、一致するオブジェクトを見つけるために常にデータベースを検索します。
import oracle.toplink.sessions.*;
import oracle.toplink.expressions.*;
/* Use an expression to read in the employee whose last name is Smith. Create an expression using the Expression Builder and use it as the selection criterion of the search */
Employee employee = (Employee) session.readObject(Employee.class, new ExpressionBuilder().get("lastName").equal("Smith"));
readAllObjects
メソッドは、データベースからオブジェクトのVector
を取得します。返されるオブジェクトの順序は指定しません。問合せで一致するオブジェクトが見つからない場合は、空のVector
が返されます。
問合せに対するクラスを指定します。例94-2に示すように、式を含めてさらに複雑な検索基準を定義することもできます。
セッション問合せAPIを使用すると、次の作成、更新および削除操作を実行できます。
writeObject
メソッドを起動すると、オブジェクトが存在するかどうかを特定するための存在チェックが実行されます。オブジェクトが存在する場合、writeObject
はオブジェクトを更新し、存在しない場合は新規オブジェクトを挿入します。
writeObject
メソッドは、参照整合性が維持されるように、正しい順序で私有されたオブジェクトを書き込みます。
オブジェクトがデータベースに存在するかどうかを確認できない場合は、writeObject
メソッドをコールします。
writeAllObjects()
メソッドをコールすると、データベースに複数のオブジェクトを書き込むことができます。writeAllObjects()
メソッドは、writeObject()
メソッドの場合と同じ存在チェックを実行した後、適切な挿入操作または更新操作を実行します。
例94-4 writeAllObjectsを使用した複数のオブジェクトの書込み
// Read a Vector of all the current employees in the database. Vector employees = (Vector) session.readAllObjects(Employee.class); ...// Modify any employee data as necessary // Create a new employee and add it to the list of employees Employee susan = new Employee(); ... // Initialize the new instance of employee employees.add(susan); /* Write all employees to the database. The new instance of susan not currently in the database will be inserted. All the other employees currently stored in the database will be updated */ session.writeAllObjects(employees);
insertObject
メソッドはデータベースで新規オブジェクトを作成しますが、挿入操作を試みる前に存在チェックを実行しません。オブジェクトがまだデータベースに存在しないことが確実な場合は、insertObject
メソッドは、writeObject
メソッドより効率的です。オブジェクトが存在する場合にinsertObject
メソッドを実行すると、データベースで例外がスローされます。
updateObject
メソッドはデータベース内の既存のオブジェクトを更新しますが、更新操作を試みる前に存在チェックを実行しません。オブジェクトがデータベースに存在することが確実な場合は、writeObject
メソッドよりもupdateObject
の方が効率的です。オブジェクトが存在しない場合にupdateObject
メソッドを実行すると、データベースで例外がスローされます。
この項では、DatabaseQuery
問合せの作成および実行により次のような様々な基本永続化操作を実行する方法について説明します。
この項では例をあげ、次のようなDatabaseQuery
を使用したオブジェクトの読取り方法について説明します。
例94-5は、単純な読取り問合せを示しています。この例では、TopLinkの式を使用しますが、問合せ用の独自の引数は使用しません。かわりに、式で提供される検索パラメータを使用します。また、コード内に式を作成しますが、問合せをセッションに登録しません。
// This example returns a Vector of employees whose employee ID is > 100 // Initialize the DatabaseQuery by specifying the query type // and set the reference class for the query ReadAllQuery query = new ReadAllQuery(Employee.class); // Retrieve ExpressionBuilder from the query ExpressionBuilder builder = query.getExpressionBuilder(); /* Configure the query execution. Because this example uses an expression, it uses the setSelectionCriteria method */ query.setSelectionCriteria(builder.get("id").greaterThan(100)); // Execute the query Vector employees = (Vector) session.executeQuery(query);
例94-6は、使用可能な構成オプションをすべて使用した、複雑なreadObject
問合せを示しています。
// Initialize the DatabaseQuery by specifying the query type // and set the reference class for the query ReadObjectQuery query = new ReadObjectQuery(Employee.class); // Retrieve ExpressionBuilder from the query ExpressionBuilder builder = query.getExpressionBuilder(); // Define two expressions that map to the first and last names of the employee Expression firstNameExpression = emp.get("firstName").equal(emp.getParameter("firstName")); Expression lastNameExpression = emp.get("lastName").equal(emp.getParameter("lastName")); /* Configure the query execution. Because this example uses an expression, it uses the setSelectionCriteria method */ query.setSelectionCriteria(firstNameExpression.and(lastNameExpression)); // Specify the required arguments for the query query.addArgument("firstName"); query.addArgument("lastName"); // Add the query to the session session.addQuery("getEmployeeWithName", query); /* Execute the query by referencing its name and providing values for the specified arguments */ Employee employee = (Employee) session.executeQuery("getEmployeeWithName","Bob","Smith");
例94-7は、部分オブジェクト読取りの使用方法を示しています。部分オブジェクト読取りでは、従業員の姓と主キーのみが読み取られます。その結果、データベースから読み取られるデータの量が減少します。
例94-7 部分オブジェクト読取りによる最適化
/* Read all the employees from the database, ask the user to choose one and return it. This uses partial object reading to read just the last name of the employees. Since TopLink automatically includes the primary key of the object, the full object can easily be read for editing */ List list; // Fetch data from database and add to list box ReadAllQuery query = new ReadAllQuery(Employee.class); query.addPartialAttribute("lastName"); // The next line avoids a query exception query.dontMaintainCache(); Vector employees = (Vector) session.executeQuery(query); list.addAll(employees); // Display list box .... // Get selected employee from list Employee selectedEmployee = (Employee)session.readObject(list.getSelectedItem()); return selectedEmployee;
例94-8では、カナダ人従業員の合計給与と平均給与が都市別に報告されます。
ExpressionBuilder emp = new ExpressionBuilder(); ReportQuery query = new ReportQuery(Employee.class, emp); query.addMaximum("max-salary", emp.get("salary")); query.addAverage("average-salary", emp.get("salary")); query.addAttribute("city", emp.get("address").get("city")); query.setSelectionCriteria(emp.get("address").get("country").equal("Canada")); query.addOrdering(emp.get("address").get("city")); query.addGrouping(emp.get("address").get("city")); Vector reports = (Vector) session.executeQuery(query);
Report
Q
uery
クラスには、属性の平均、最大、最小、合計、標準偏差、分散、総数を計算するメソッドなど、広範なレポートAPIがあります。Report
Q
uery
で使用可能なメソッドの詳細は、『Oracle Application Server TopLink API Reference』を参照してください。
注意: ReportQuery はReadAllQuery から継承されているため、ほとんどのReadAllQuery プロパティもサポートします。 |
例による問合せを使用すると、問合せで使用する属性のみを移入したサンプル・オブジェクト・インスタンスの形式で、問合せ選択基準を指定できます。
例による問合せを定義するには、ReadObjectQuery
またはReadAllQuery
を、永続オブジェクトのサンプル・インスタンスおよび例による問合せポリシー(オプション)とともに指定します。サンプル・インスタンスには、問い合せるデータと、オプションでQueryByExamplePolicy
(「QueryByExamplePolicyの定義」を参照)を含めます。QueryByExamplePolicy
には、使用する演算子や無視する属性値など、構成設定を指定します。また、例による問合せと式を組み合せることもできます(「例による問合せと式の結合」を参照)。
詳細は、「例による問合せ」を参照してください。
例94-9 例による問合せを使用した従業員の問合せ
例94-9では、従業員Bob Smithを問い合せています。
Employee employee = new Employee();
employee.setFirstName("Bob");
employee.setLastName("Smith");
// Create a query and set Employee as its reference class
ReadObjectQuery query = new ReadObjectQuery(Employee.class);
query.setExampleObject(employee);
Employee result = (Employee) session.executeQuery(query);
例94-10 例による問合せを使用した従業員の住所の問合せ
例94-10では、従業員の住所に対して問合せを行っています。
Employee employee = new Employee();
Address address = new Address();
address.setCity("Ottawa");
employee.setAddress(address);
// Create a query and set Employee as its reference class
ReadObjectQuery query = new ReadObjectQuery(Employee.class);
query.setExampleObject(employee);
Vector results = (Vector) session.executeQuery(query);
QueryByExamplePolicyの定義
TopLinkの例による問合せサポートには、例による問合せポリシーも含まれています。このポリシーを編集すると、例による問合せのデフォルト動作を変更できます。次のような場合のために、ポリシーを変更できます。
LIKE
などの演算子を使用して、属性を比較する場合。デフォルトでは、例による問合せで使用できるのはEQUALS
のみです。
例による問合せで無視される値のセット(IGNORE
セット)を変更する場合。デフォルトで無視される値は、ゼロ(0)、空の文字列およびFALSE
です。
属性の値がIGNORE
セットに含まれるものであっても、例による問合せでその値を強制的に考慮する場合。
属性値としてisNull
またはnotNull
を使用する場合。
例による問合せポリシーを指定するには、問合せにQueryByExamplePolicy
のインスタンスを含めます。
例94-11 like演算子を使用した例による問合せポリシー
例94-11では、文字列に対してlike
演算子を使用し、給与がゼロを超えるオブジェクトのみを含めています。
Employee employee = new Employee(); employee.setFirstName("B%"); employee.setLastName("S%"); employee.setSalary(0); // Create a query and set Employee as its reference class ReadAllQuery query = new ReadAllQuery(Employee.class); query.setExampleObject(employee); // Query by example policy section adds like and greaterThan QueryByExamplePolicy policy = new QueryByExamplePolicy(); policy.addSpecialOperation(String.class, "like"); policy.addSpecialOperation(Integer.class, "greaterThan"); policy.alwaysIncludeAttribute(Employee.class, "salary"); query.setQueryByExamplePolicy(policy); Vector results = (Vector) session.executeQuery(query);
例94-12 キーワードを使用した例による問合せポリシー
例94-12では、文字列に対してキーワードを使用し、値-1を無視します。
Employee employee = new Employee(); employee.setFirstName("bob joe fred"); employee.setLastName("smith mc mac"); employee.setSalary(-1); // Create a query and set Employee as its reference class ReadAllQuery query = new ReadAllQuery(Employee.class); query.setExampleObject(employee); // Query by example policy section QueryByExamplePolicy policy = new QueryByExamplePolicy(); policy.addSpecialOperation(String.class, "containsAnyKeyWords"); policy.excludeValue(-1); query.setQueryByExamplePolicy(policy); Vector results = (Vector) session.executeQuery(query);
例による問合せと式の結合
例94-13に示すように、さらに複雑な例による問合せを作成するには、例による問合せをTopLinkの式と結合します。
例94-13 例による問合せと式の結合
Employee employee = new Employee(); employee.setFirstName("Bob"); employee.setLastName("Smith"); // Create a query and set Employee as its reference class ReadAllQuery query = new ReadAllQuery(Employee.class); query.setExampleObject(employee); // Specify expression ExpressionBuilder builder = query.getExpressionBuilder(); query.setSelectionCriteria(builder.get("salary").between(100000,200000); Vector results = (Vector) session.executeQuery(query);
順序付けは、DatabaseQuery
の一般的なオプションです。TopLink Workbenchの「順序」タブを使用し、JavaコードでReadAllQuery
、addOrdering
、addAscendingOrdering
、addDescendingOrdering
メソッドを使用して、返されるオブジェクトのコレクションの順序を指定します。属性名または問合せキーと式に基づいた順序を適用できます。
例94-14 単純な順序付けを行う問合せ
// Retrieves objects ordered by last name then first name in ascending order
ReadAllQuery query = new ReadAllQuery(Employee.class);
query.addAscendingOrdering ("lastName");
query.addAscendingOrdering ("firstName");
Vector employees = (Vector) session.executeQuery(query);
例94-15 複雑な順序付けを行う問合せ
/* Retrieves objects ordered by street address, descending case-insensitive order of cities, and manager's last name */
ReadAllQuery query = new ReadAllQuery(Employee.class);
ExpressionBuilder emp = query.getExpressionBuilder();
query.addOrdering (emp.getAllowingNull("address").get("street"));
query.addOrdering(
emp.getAllowingNull("address").get("city").toUpperCase().descending());
query.addOrdering(emp.getAllowingNull("manager").get("lastName"));
Vector employees = (Vector) session.executeQuery(query);
getAllowingNull
を使用し、住所とマネージャのリレーションシップの外部結合を作成していることに注意してください。これにより、住所またはマネージャを持たない従業員もリストに含まれます。
読取り順序の構成の詳細は、「すべて読取り問合せの順序の構成」を参照してください。
デフォルトでは、ReadAllQuery
は結果オブジェクトをVectorで返します。例94-16に示すように、この問合せを、Collection
またはMap
インタフェースを実装する任意のコレクション・クラスで結果を返すように構成できます。
指定した最大行数に問合せを制限できます。この機能を使用して、非常に多くのオブジェクトが返される可能性のある問合せを回避します。
例94-18に示すように、最大行数を指定するには、setMaxRows
メソッドを使用し、問合せの最大行数を表す整数を渡します。
例94-18 返されるオブジェクトの最大サイズの設定
ReadAllQuery query = new ReadAllQuery(Employee.class); query.setMaxRows(5); Vector employees = (Vector) session.executeQuery(query);
setMaxRows
メソッドでは問合せが返す行数が制限されますが、最初の結果セットの後にその行数を超えるレコードを取得することはできません。
固定の増分で結果セットを参照するには、カーソルまたはカーソル付きストリームを使用します。詳細は、「カーソルとストリームの問合せ結果の処理」を参照してください。
TopLinkで問合せ結果を待つ最大時間を設定できます。これを設定した場合、指定時間が過ぎると、ハングしている問合せや長時間かかっている問合せが強制的に中断されます。タイムアウト時間が経過すると、DatabaseException
がスローされます。
例94-19に示すように、問合せごとにタイムアウト時間を指定するには、DatabaseQuery
のメソッドsetQueryTimeout
を使用し、タイムアウト時間を、タイムアウト時間が経過するまでの秒数を表す整数として渡します。
// Create the appropriate query and set timeout limits ReadAllQuery query = new ReadAllQuery(Employee.class); query.setQueryTimeout(2); try{ Vector employees = (Vector)session.executeQuery(query); } catch (DatabaseException ex) { // timeout occurs }
特定のオブジェクト・タイプに対するすべての問合せに関してタイムアウト時間を指定するには、ディスクリプタ・レベルで問合せタイムアウト時間を構成します(「ディスクリプタ・レベルでの問合せタイムアウトの構成」を参照)。
バッチ読取りでは、オブジェクトのリレーションシップ属性のマッピングを通じて、問合せの選択基準が伝播されます。バッチ読取り操作を複雑なオブジェクト・グラフにネストさせることもできます。そうすることで、必要なSQLのSELECT文の数が大幅に減少し、データベース・アクセスが効率化されます。
バッチ読取りを実装する際は、次のガイドラインに留意してください。
バッチ読取りは、オブジェクトとそのすべての関連オブジェクトを読み取るプロセスに使用します。
双方向リレーションシップの両側でバッチ読取りを有効にしないでください。
バッチ読取り操作のネストは、データベースで複数の結合が発生して問合せの実行速度が低下する原因となるため、避けてください。
詳細は、「読取り例2: オブジェクトのバッチ読取り」を参照してください。
たとえば、n名の従業員とその関連プロジェクトを読み取る場合、選択操作をn + 1回行う必要があります。従業員はすべて一度に読み取られますが、各従業員のプロジェクトはそれぞれ個別に読み取られます。バッチ読取りを使用すれば、関連プロジェクトも元の選択基準を使用してすべて一度の選択操作で読み取ることができるため、選択操作の回数は合計2回のみとなります。
バッチ読取りを実装するには、次のいずれかのメソッドを使用します。
バッチ読取り属性を問合せに追加するには、query.addBatchReadAttribute(Expression anExpression)
APIを使用します。
例:
… ReadAllQuery raq = new ReadAllQuery(Trade.class); ExpressionBuilder tradeBuilder = raq.getBuilder(); … Expression batchReadProduct = tradeBuilder.get("product"); readAllQuery.addBatchReadAttribute(batchReadProduct); Expression batchReadPricingDetails = batchReadProduct.get("pricingDetails"); readAllQuery.addBatchReadAttribute(batchReadPricingDetails); …
ディスクリプタのマッピング・レベルでバッチ読取りを追加します。TopLink Workbenchまたはディスクリプタ修正メソッドを使用して、ディスクリプタのリレーションシップ・マッピングでsetUsesBatchReading
APIを追加します。
例:
public static void amendTradeDescriptor(Descriptor theDescriptor) { OneToOneMapping productOneToOneMapping = theDescriptor.getMappingForAttributeName("product"); productOneToOneMapping.setUsesBatchReading(true); }
バッチ読取りとインダイレクションを組み合せると、オブジェクトの属性の読取りを制御できます。たとえば、1対1のバックポインタ・リレーションシップ属性がある場合、問合せの最後に親の所有側オブジェクトがすべてインスタンス化されるまで、バックポインタのインスタンス化を遅らせることができます。これにより、不要なデータベース・アクセスが防止され、TopLinkキャッシュの使用状況が最適化されます。
結合読取りを使用すると、クラスの問合せを構成して、クラスのインスタンスおよび関連オブジェクトのインスタンスを作成するデータが返されるようにできます。詳細は、「結合読取りとオブジェクト・レベルの読取り問合せ」を参照してください。
結合された1つ以上の属性を問合せに追加するには、TopLink WorkbenchまたはJavaを使用できます。
TopLink Workbenchを使用して、結合された1つ以上の属性を問合せに追加するには、名前付き問合せ(「名前付き問合せの最適化の構成」を参照)を定義する際に、結合属性を構成します。1対多のマップ属性についての結合式を使用してObjectLevelReadQuery
を作成する場合は、TopLink Workbenchは使用できません。この場合はJavaを使用する必要があります。
ObjectLevelReadQuery
APIを使用して、1対1および1対多のリレーションシップに結合属性を追加できます。
ObjectLevelReadQuery
のメソッドaddJoinedAttribute(Expression attributeExpression)
を使用すると、結合式を問合せに追加できます。このメソッドを使用して、ネストされた結合を含む、複数の結合属性を1対1および1対多のリレーションシップに追加できます。ソースおよびターゲットは、同じクラス・タイプにすることができます。ObjectLevelReadQuery
のメソッドaddJoinedAttribute
は、多対多のマップ属性についての結合式では、使用できません。
1対1のマップ属性についての結合式でObjectLevelReadQuery
のメソッドaddJoinedAttribute
を使用すると、データベースに1回アクセスすることにより、ObjectLevelReadQuery
のクラス、およびそのクラスの1対1にマップされた属性のターゲットを取得できます。
1対多のマップ属性についての結合式を持つObjectLevelReadQuery
のメソッドaddJoinedAttribute
を使用すると、データベースに1回アクセスすることにより、ObjectLevelReadQuery
のクラス、およびそのクラスの1対多にマップされた属性のターゲット・コレクションを取得できます。
例94-20は、TopLink ThreeTierEmployee
サンプル・オブジェクトをベースにしています。この例では、ReadAllQuery
が複数属性の結合読取りを行うように構成されています。この問合せにより、例94-21で示すSQLが生成されます。
例94-20 複数属性の結合読取り
ReadAllQuery query = new ReadAllQuery(Employee.class); Expression managedEmployees = query.getExpressionBuilder().anyOfAllowingNone( "managedEmployees" ); query.addJoinedAttribute(managedEmployees); query.addJoinedAttribute(managedEmployees.get("address")); query.addJoinedAttribute(managedEmployees.anyOf("phoneNumbers")); Vector employees = (Vector)getSession().executeQuery(query);
例94-21 複数属性の結合読取りを行うSQL
SELECT DISTINCT t2.VERSION, t3.EMP_ID, t2.GENDER, t3.SALARY, t2.EMP_ID, t2.F_NAME, t2.L_NAME, t2.MANAGER_ID, t2.ADDR_ID, t2.END_DATE, t2.START_DATE, t2.END_TIME, t2.START_TIME, t0.VERSION, t1.EMP_ID, t0.GENDER, t1.SALARY, t0.EMP_ID, t0.F_NAME, t0.L_NAME, t0.MANAGER_ID, t0.ADDR_ID, t0.END_DATE, t0.START_DATE, t0.END_TIME, t0.START_TIME FROM SALARY t3, EMPLOYEE t2, SALARY t1, EMPLOYEE t0 WHERE ((t3.EMP_ID = t2.EMP_ID) AND ((t0.MANAGER_ID (+) = t2.EMP_ID) AND (t1.EMP_ID (+) = t0.EMP_ID)))
ObjectLevelReadQuery
のメソッドaddJoinedAttribute(java.lang.String attributeName)
を使用すると、例94-22に示すように、1つの属性の結合読取りを行うように問合せを構成できます。
この項の内容は次のとおりです。
書込み問合せを実行するには、セッションのwriteObject
メソッドを使用するかわりに、WriteObjectQuery
インスタンスを使用します。同様に、DeleteObjectQuery
、UpdateObjectQuery
、InsertObjectQuery
の各オブジェクトをそれぞれのSession
メソッドのかわりに使用します。
例94-23 WriteObjectQueryの使用
WriteObjectQuery writeQuery = new WriteObjectQuery(); writeQuery.setObject(domainObject); session.executeQuery(writeQuery);
例94-24 InsertObjectQuery、UpdateObjectQueryおよびDeleteObjectQueryの使用
InsertObjectQuery insertQuery= new InsertObjectQuery(); insertQuery.setObject(domainObject); session.executeQuery(insertQuery); /* When you use UpdateObjectQuery without a unit of work, UpdateObjectQuery writes all direct attributes to the database */ UpdateObjectQuery updateQuery= new UpdateObjectQuery(); updateQuery.setObject(domainObject2); session.executeQuery(updateQuery); DeleteObjectQuery deleteQuery = new DeleteObjectQuery(); deleteQuery.setObject(domainObject2); session.executeQuery(deleteQuery);
UpdateAllQueryを使用すると、一度に多数のオブジェクトを更新できます。この問合せを使用すると、オブジェクトをメモリーに読み取って個別に更新するかわりに、1つのSQL文で多数のオブジェクトを更新できます。例94-25では、すべての常勤従業員を昇給させるUpdateAllQuery
を示しています。
例94-25 UpdateAllQueryの使用
// Give all full time employees a 10% raise
UpdateAllQuery updateQuery = new UpdateAllQuery(Employee.class);
ExpressionBuilder employee = updateQuery.getExpressionBuilder();
updateQuery.setSelectionCriteria(eb.get("status").equal("FULL_TIME"));
updateQuery.addUpdateExpression(employee.get("salary"),
ExpressionMath.multiply(employee.get("salary"), new Float(1.10)));
同一のSQL文では複数の表を更新できないため、UpdateAllQuery
では、複数の表にわたるオブジェクト、または継承をサポートしていません。また、UpdateAllQuery
は、独自のトランザクションから実行する必要があります。このため、作業ユニットにはこの問合せのみを含めてください。UnitOfWork
のメソッドexecuteQuery
を使用します。
非JTAトランザクションの場合、TopLinkでは作業ユニットとセッション実行がサポートされます。JTAトランザクションの場合、作業ユニットのみがサポートされます(セッション実行はサポートされません)。トランザクションの詳細は、第97章「TopLinkトランザクションの概要」を参照してください。
UpdateAllQueryでは、キャッシュが使用され、キャッシュは常に最新の状態に維持されます。UpdateAllQueryを構成してキャッシュを無効化するには(「キャッシュの無効化」を参照)、キャッシュの使用状態をINVALIDATE_CACHE
(デフォルト)に設定するか、NO_CACHE
オプションを指定してキャッシュの使用を停止します。これらの設定は、setCacheUsage
メソッドを通じて操作できます。一致する式のキャッシュのみを更新できます。キャッシュの詳細は、第87章「キャッシュの概要」を参照してください。
UpdateAllQueryでは、単方向の1対1リレーションシップのみがサポートされます。ダイレクト・マッピングは完全にサポートされ、集約マッピングは部分的にサポートされます(第IX部「マッピング」を参照)。
注意: 属性は集約内にのみ設定できます。集約全体に対しては設定できません。 |
これらの問合せでは外部キーの更新がサポートされないため、これらの問合せを使用して外部キー・フィールドにNULL
を設定することはできません。
UpdateAllQueryをオプティミスティック・ロック(「ディスクリプタとロックの概要」を参照)と組み合せ、データベースの行を更新するレベルで使用できます。この場合、キャッシュの更新は行われません(データベースのロック・フィールドが更新されます)。また、バージョンおよびタイムスタンプ・ロックのサポートに加え、フィールド・ロックの間接的サポートも提供されます。
書込み問合せを実行すると、デフォルトではオブジェクトとその私有された部分の両方がデータベースに書き込まれます。私有された部分を更新しない書込み問合せを作成するには、問合せの定義にdontCascadeParts
メソッドを含めます。
このメソッドは、次の目的で使用します。
オブジェクトのダイレクト属性のみが変更されたことがわかっている場合に、パフォーマンスを向上させること。
独立した新規オブジェクトの大きなグループを作成する場合に、参照整合性の依存関係を解決すること。
注意: 作業ユニットでは参照整合性が内部的に解決されるため、作業ユニットを使用してデータベースに書き込む場合はこのメソッドは不要です。 |
データベースにオブジェクトを書き込む場合、TopLinkでは、デフォルトでセッション・キャッシュにオブジェクトがコピーされます。問合せにおけるこの動作を無効にするには、問合せでdontMaintainCache
メソッドをコールします。そうすることで、データベースにオブジェクトを挿入する際の問合せのパフォーマンスが向上しますが、この方法は後でアプリケーションで必要にならないオブジェクトに対してのみ使用できます。
例94-27 書込み問合せ中のアイデンティティ・マップ・キャッシュの無効化
例94-27は、フラット・ファイルからすべてのオブジェクトを読み取り、オブジェクトの新規コピーを表に書き込みます。
// Reads objects from an employee file and writes them to the employee table void createEmployeeTable(String filename, Session session) { Iterator iterator; Employee employee; // Read the employee data file List employees = Employee.parseFromFile(filename); Iterator iterator = employees.iterator(); while (iterator.hasNext()) { Employee employee = (Employee) iterator.next(); InsertObjectQuery query = new InsertObjectQuery(); query.setObject(employee); query.dontMaintainCache(); session.executeQuery(query); } }
注意: アイデンティティ・マップを無効にするのは、後続の操作においてオブジェクト・アイデンティティが重要ではない場合にかぎってください。 |
この項の内容は次のとおりです。
例94-28に示すように、DataReadQuery
を使用すると、結果セットを表すDatabaseRows
のCollection
を返す選択SQL文字列を実行できます。
例94-29に示すように、DirectReadQuery
は、データの1列(1つのフィールド)を読み取り、結果セットを表すDatabaseRows
のCollection
を返すために使用できます。
ValueReadQuery
を使用すると、単一データ値(1つのフィールド)を読み取ることができます。例94-30に示すように、単一データ値が返されます。または、行が返されない場合は、nullが返されます。
例94-30 ValueReadQueryの使用
ValueReadQuery valueReadQuery = new ValueReadQuery();
valueReadQuery.setSQLString("SELECT DISTINCT CURRENT TIMESTAMP FROM SYSTABLES");
// result is a single Object value
Object result = session.executeQuery(valueReadQuery);
警告: 検証されていないSQL文字列をメソッド(たとえば |
例94-31に示すように、DataModifyQuery
を使用すると、選択を行わないSQL文を(直接またはSQLCall
として)実行できます。これは、Session
のメソッドexecuteNonSelectingCall
と同等です(「SQLCallの使用」を参照)。
すべてのDatabaseQuery
オブジェクトには、カスタムSQL文字列を定義できるsetSQLString
メソッドが用意されています。
問合せにおけるカスタムSQLの使用方法の詳細は、「SQLコールの使用」を参照してください。
例94-32では、SQLを使用してすべての従業員IDを読み取っています。
例94-32 SQLを使用したダイレクト読取り問合せ
DirectReadQuery query = new DirectReadQuery(); query.setSQLString("SELECT EMP_ID FROM EMPLOYEE"); Vector ids = (Vector) session.executeQuery(query);
例94-33では、SQLを使用して別のデータベースに切り替えています。
例94-33 SQLを使用したデータ変更問合せ
DataModifyQuery query = new DataModifyQuery(); query.setSQLString("USE SALESDATABASE"); session.executeQuery(query);
警告: 検証されていないSQL文字列をメソッド(たとえば |
すべてのDatabaseQuery
オブジェクトには、カスタムEJB QL文字列を指定できるsetEJBQLString
メソッドが用意されています。
問合せにおけるカスタムEJB QLの使用方法の詳細は、「EJB QLコールの使用」を参照してください。
参照クラスおよびSELECT
句の両方を指定し、問合せを通常どおり実行します。
例94-34 EJB QL
ReadAllQuery query = new ReadAllQuery(EmployeeBean.class); query.setEJBQLString("SELECT OBJECT(emp) FROM EmployeeBean emp"); … Vector returnedObjects = (Vector)session.executeQuery(query);
例94-35は例94-34と同様の問合せを定義したものですが、引数のVectorを作成して埋め込み、executeQuery
メソッドに渡しています。
例94-35 EJB QLを使用し、引数を渡す単純なReadAllQuery
// First define the query ReadAllQuery query = new ReadAllQuery(EmployeeBean.class); query.setEJBQLString("SELECT OBJECT(emp) FROM EmployeeBean emp WHERE emp.firstName = ?1"); query.addArgument("1", String.class); ... // Next define the arguments Vector arguments = new Vector(); arguments.add("Bob"); ... // Finally, execute the query passing in the arguments Vector returnedObjects = (Vector)session.executeQuery(query, arguments);
個々の問合せでパラメータ使用のSQLを有効にするには、DatabaseQuery
のメソッドbindAllParameters
およびcacheStatement
を使用します。そうすることで、TopLinkではプリコンパイルされたSQL文を使用し、すべてのSQLパラメータをバインドして、プリコンパイルされたSQL文をキャッシュします。この問合せを再実行するときにはSQLのプリコンパイルが不要になるため、パフォーマンスが向上します。
例94-36 パラメータ使用のSQLによる単純なReadObjectQuery
ReadObjectQuery query = new ReadObjectQuery(Employee.class); query.setShouldBindAllParameters(true); query.setShouldCacheStatement(true);
または、すべての問合せに対してログイン・レベルでパラメータ使用のSQLおよびバインドを構成できます(「JDBCオプションの構成」を参照)。
データ・アクセスの最適化のためのパラメータ使用のSQLおよびバインドの使用方法の詳細は、「パラメータ使用のSQL(バインド)とプリコンパイルされたSQL文のキャッシュ」を参照してください。
注意: J2EEデータ・ソースまたは外部接続プールを使用するアプリケーションでは、TopLinkにおいてではなくJ2EEサーバーのデータ・ソースにおいて、文のキャッシュを構成する必要があります。 |
名前付き問合せは、一度作成すると、基礎となる関連オブジェクトすべてとともに後で効率的に再利用できるため、頻繁に実行される操作に適しており、アプリケーションのパフォーマンスを向上させることができます。
名前付き問合せはセッション・レベル(「セッション・レベルでの名前付き問合せの構成」を参照)またはディスクリプタ・レベル(「ディスクリプタ・レベルでの名前付き問合せの構成」を参照)で構成できます。
セッション・レベルでの名前付き問合せの場合は、次のセッションAPIコールのいずれかを使用して問合せを実行できます。
executeQuery(String queryName)
executeQuery(String queryName, arg1)
executeQuery(String queryName, arg1, arg2)
executeQuery(String queryName, arg1, arg2, arg3)
executeQuery(String queryName, Vector args)
例94-37 セッション・レベルでの名前付き問合せの実行
Vector args = new Vector(); args.add("Sarah"); Employee sarah = (Employee)session.executeQuery( "employeeReadByFirstName", args );
ディスクリプタ・レベルでの名前付き問合せの場合は、例94-38に示すように、次のセッションAPIコールのいずれかを使用して問合せを実行できます。
executeQuery(String queryName, Class domainClass)
executeQuery(String queryName, Class domainClass, arg1)
executeQuery(String queryName, Class domainClass, arg1, arg2)
executeQuery(String queryName, Class domainClass, arg1, arg2, arg3)
executeQuery(String queryName, Class domainClass, Vector args)
例94-38 ディスクリプタ・レベルでの名前付き問合せの実行
Vector args = new Vector(); args.add("Sarah"); Employee sarah = (Employee)session.executeQuery( "ReadByFirstName", Employee.class, args );
詳細は、「名前付き問合せ」を参照してください。
TopLinkの式フレームワークを使用すると、複雑な問合せをオブジェクト・レベルで定義できます。アプリケーションでより複雑な問合せ、またはデータやストアド・プロシージャに直接アクセスする問合せを必要とする場合は、カスタムSQL文字列をSQL Call
オブジェクトに指定し、そのCall
オブジェクトを問合せに指定できます。
また、DatabaseQuery
に直接SQL文字列を指定することもできます。詳細は、「DatabaseQueryにおけるカスタムSQL文字列の指定」を参照してください。
SQLコールを使用する際に、ReturningPolicy
を使用して、TopLinkでパラメータに書き込むかまたはデータベースによって生成された値を取得するかを制御できます。詳細は、「ReturningPolicyの構成」を参照してください。
この項の内容は次のとおりです。
どのような問合せにも式のかわりにSQLCall
オブジェクトを指定できますが、SQLCall
に含まれるSQL文字列は、問い合せたクラスのインスタンスの作成に必要なデータをすべて返す必要があります。
SQL文字列には、複雑なSQL問合せ、ストアド・プロシージャ・コールまたはストアド・ファンクション・コールを指定できます。入力、出力、および入出力パラメータを指定できます。
SQLCall
は、セッション問合せメソッド(例94-39を参照)またはDatabaseQuery
を通じて起動できます。
例94-39 カスタムSQLを使用したセッション読取り問合せ
List result = session.executeSelectingCall( new SQLCall("SELECT * FROM EMPLOYEE WHERE EMP_ID = 44"));
警告: 検証されていないSQL文字列をメソッドに渡せるようにすると、SQLインジェクション攻撃に対してアプリケーションが脆弱になります。 |
TopLinkでは、SQLCall
のカスタムSQL文字列のトークンの先頭に1つ以上のシャープ記号(#
)が付いている場合は、そのトークンがパラメータであるものとみなします。次の各項で説明するように、問合せAPIを使用して、これらのパラメータに値をバインドすることができます。
例94-40において、last_name
は、その先頭にシャープ記号(#
)を1つ付けることで、入力パラメータとして指定されています。例94-41では、問合せの実行時にこの入力パラメータに値をバインドする方法を示します。
例94-42において、employee_id
は、その先頭にシャープ記号を3つ(###
)付けることで、出力パラメータとして指定されています。出力パラメータのタイプは、SQLCall
のメソッドsetCustomSQLArgumentType
を使用して指定します。last_name
は、この例でも、その先頭にシャープ記号(#
)を付けることで入力パラメータとして指定されています。
例94-42 出力パラメータ(接頭辞###付き)を持つSQLCallの指定
SQLCall sqlCall = new SQLCall("begin; INSERT INTO EMPLOYEE (L_NAME) VALUES (#L_NAME) RETURNING EMP_ID INTO ###employee_id; end"); sqlCall.setCustomSQLArgumentType("employee_id", Integer.class);
例94-43 出力パラメータを持つSQLCallの実行
ValueReadQuery query = new ValueReadQuery();
query.setCall(sqlCall);
query.addArgument("last_name"); // input
Vector args = new Vector();
args.add("MacDonald");
Number employeeID = (Number)getSession().executeQuery(query, args);
タイプCURSOR
として宣言された出力パラメータの結果を取得することもできます。
例94-44において、in_out
は、その先頭にシャープ記号を4つ(####
)付けることで、入出力パラメータとして指定されています。入力値のタイプによって、出力値のタイプが決まります。この例では、String
(MacDonald)が渡され、EMP_ID
の出力値がString
として返されます。
どのような問合せにも式またはSQL文字列のかわりにStoredProcedureCall
オブジェクトを指定できますが、プロシージャは問い合せたクラスのインスタンスの作成に必要なデータをすべて返す必要があります。
例94-46 ストアド・プロシージャを使用したすべて読取り問合せ
ReadAllQuery readAllQuery = new ReadAllQuery(); call = new StoredProcedureCall(); call.setProcedureName("Read_All_Employees"); call.useNamedCursorOutputAsResultSet("RESULT_SET"); readAllQuery.setCall(call); Vector employees = (Vector) session.executeQuery(readAllQuery);
StoredProcedureCall
を使用すると、次のことが可能になります。
注意: OUT またはINOUT パラメータを持つStoredProcedureCall を使用する際に、DatabaseQuery のメソッドbindAllParameters を使用する必要がなくなりました。ただし、すべてのOUT およびINOUT パラメータのJavaタイプを必ず指定する必要があります。これを指定しないと、デフォルトとしてタイプString が使用されることに注意してください。 |
例94-47では、StoredProcedureCall
のメソッドaddNamedArgument
を使用して、入力パラメータとしてパラメータPOSTAL_CODE
を指定し、その値をメソッドaddNamedArgumentValue
に指定できます。
例94-47 入力パラメータを使用したストアド・プロシージャ・コール
StoredProcedureCall call = new StoredProcedureCall(); call.setProcedureName("CHECK_VALID_POSTAL_CODE"); call.addNamedArgument("POSTAL_CODE"); call.addNamedArgumentValue("POSTAL_CODE", "L5J1H5"); call.addNamedOutputArgument( "IS_VALID", // procedure parameter name "IS_VALID", // out argument field name Integer.class // Java type corresponding to type returned by procedure ); ValueReadQuery query = new ValueReadQuery(); query.setCall(call); Number isValid = (Number)session.executeQuery(query);
出力パラメータを使用すると、ストアド・プロシージャから追加の情報が返されます。オブジェクトの作成に必要なすべてのフィールドが返されれば、出力パラメータを使用してReadObjectQuery
を定義できます。
例94-48では、StoredProcedureCall
のメソッドaddNamedOutputArgument
を使用して、パラメータIS_VALIDを出力パラメータとして指定します。
例94-48 出力パラメータを使用したストアド・プロシージャ・コール
StoredProcedureCall call = new StoredProcedureCall(); call.setProcedureName("CHECK_VALID_POSTAL_CODE"); call.addNamedArgument("POSTAL_CODE"); call.addNamedOutputArgument( "IS_VALID", // procedure parameter name "IS_VALID", // out argument field name Integer.class // Java type corresponding to type returned by procedure ); ValueReadQuery query = new ValueReadQuery(); query.setCall(call); query.addArgument("POSTAL_CODE"); Vector parameters = new Vector(); parameters.addElement("L5J1H5"); Number isValid = (Number)session.executeQuery(query,parameters);
注意: データを返す出力パラメータの使用をサポートしていないデータベースもあります。ただし、このようなデータベースは一般的にストアド・プロシージャからの結果セットの返却をサポートしているため、出力パラメータを必要としません。 |
Oracleデータベースを使用している場合、TopLinkのカーソルとストリームの問合せ結果を使用できます。
例94-49では、StoredProcedureCall
のメソッドaddNamedInOutputArgumentValue
への入出力パラメータとしてパラメータLENGTH
を指定するとともに、その値を指定してストアド・プロシージャに渡します。この引数の値を指定しない場合は、メソッドaddNamedInOutputArgument
を使用します。
例94-49 入出力パラメータを使用したストアド・プロシージャ・コール
StoredProcedureCall call = new StoredProcedureCall(); call.setProcedureName("CONVERT_FEET_TO_METERs"); call.addNamedInOutputArgumentValue( "LENGTH", // procedure parameter name new Integer(100), // in argument value "LENGTH", // out argument field name Integer.class // Java type corresponding to type returned by procedure ) ValueReadQuery query = new ValueReadQuery(); query.setCall(call); Integer metricLength = (Integer)session.executeQuery(query);
TopLinkでは、出力パラメータ・イベントをサポートするデータベース用に出力パラメータ・イベントが管理されます。たとえば、アプリケーションがエラー条件のチェックを必要としていることを示すエラー・コードがストアド・プロシージャから返されると、セッション・イベントOutputParametersDetected
が発生し、アプリケーションは出力パラメータを処理することができます。
例94-50 リセット・セットと出力パラメータのエラー・コードを使用したストアド・プロシージャ
StoredProcedureCall call = new StoredProcedureCall(); call.setProcedureName("READ_EMPLOYEE"); call.addNamedArgument("EMP_ID"); call.addNamedOutputArgument( "ERROR_CODE", // procedure parameter name "ERROR_CODE", // out argument field name Integer.class // Java type corresponding to type returned by procedure ); call.useNamedCursorOutputAsResultSet("RESULT_SET"); ReadObjectQuery query = new ReadObjectQuery(); query.setCall(call); query.addArgument("EMP_ID"); ErrorCodeListener listener = new ErrorCodeListener(); session.getEventManager().addListener(listener); Vector args = new Vector(); args.addElement(new Integer(44)); Employee employee = (Employee)session.executeQuery(query, args);
StoredProcedureCall
を使用して、ストアド・プロシージャをサポートするデータベースで定義されたストアド・プロシージャを起動します。StoredFunctionCall
を使用して、ストアド・ファンクションをサポートするデータベース(つまり、DatabasePlatform
のメソッドsupportsStoredFunctions
がtrue
を返すデータベース)で定義されたストアド・ファンクションを起動することもできます。
一般的に、ストアド・プロシージャとストアド・ファンクションのどちらにおいても、入力パラメータ、出力パラメータおよび入出力パラメータを指定できます。詳細は、「StoredProcedureCallの使用」を参照してください。ただし、ストアド・プロシージャでは値を返す必要はありませんが、ストアド・ファンクションでは必ず値を1つ返します。
StoredFunctionCall
クラスは、StoredProcedureCall
を拡張して新しく1つのメソッドsetResult
を追加したものです。このメソッドを使用して、ストアド・ファンクションの戻り値の、TopLinkによる保存先の名前(または名前とタイプの両方)を指定します。
TopLinkでStoredFunctionCall
をプリコンパイルする際には、そのSQLが検証され、次の場合にValidationException
がスローされます。
ストアド・ファンクションが現在のプラットフォームでサポートされていない場合。ストアド・ファンクションは、Oracleでのみサポートされています。
戻りタイプを指定しなかった場合。
例94-51では、StoredFunctionCall
のメソッドsetProcedureName
を使用してストアド・ファンクションの名前が設定されていることに注意してください。
例94-51 StoredFunctionCallの作成
StoredFunctionCall functionCall = new StoredFunctionCall(); functionCall.setProcedureName("CHECK_VALID_EMPLOYEE"); functionCall.addNamedArgument("EMP_ID"); functionCall.setResult("FUNCTION_RESULT", String.class); ValueReadQuery query = new ValueReadQuery(); query.setCall(functionCall); query.addArgument("EMP_ID"); Vector args = new Vector(); args.addElement(new Integer(44)); String valid = (String) session.executeQuery(query, args);
TopLinkの式フレームワークを使用すると、複雑な問合せをオブジェクト・レベルで定義できます。あるいは別の方法として、カスタムEJB QL文字列をEJB QL Call
オブジェクトに指定し、そのCall
オブジェクトを任意の問合せに対して指定することもできます。
また、DatabaseQuery
に直接EJB QL文字列を指定することもできます。詳細は、「DatabaseQueryにおけるカスタムEJB QL文字列の指定」を参照してください。
どのような問合せにも式またはEJB QL文字列のかわりにEJBQLCall
オブジェクトを指定できますが、プロシージャは問い合せたクラスのインスタンスの作成に必要なデータをすべて返す必要があります。
EJB QL問合せは、セッション問合せメソッドまたはDatabaseQuery
を通じて起動できます。
EISルート・ディスクリプタの場合は、EISインタラクションを定義してEISに対してメソッドを起動できます。
TopLinkでは、EISインタラクションを表すためにoracle.toplink.eis.interactions.EISInteraction
のインスタンスを使用します。これらのクラスにはCall
インタフェースが実装されているため、Call
を使用できるところではどこでもこれらのクラスを使用できます。
表94-1は、TopLinkがサポートするEISインタラクションのタイプを示しています。
表94-1 EISインタラクション
EISインタラクションのタイプ | 説明 |
---|---|
|
索引付きレコードを使用するJ2Cインタラクションのコールの仕様定義です。位置による引数から入力レコードと出力レコードを作成します。 |
|
マップされたレコードを使用するJ2Cインタラクションのコールの仕様定義です。名前による引数から入力レコードと出力レコードを作成します。 |
|
EISプロジェクトに関連付けられたXMLスキーマ文書(XSD)によって定義されたXMLレコードを使用するJ2Cインタラクションのコールの仕様を定義する、 |
|
問合せ文字列を使用するJ2Cインタラクションのコールの仕様を定義する |
|
XQueryを使用するJ2Cインタラクションのコールの仕様を定義する |
TopLinkを使用して、基本的な永続性操作(insert
、update
、delete
、read object
、read all
またはdoes exist
)ごとにインタラクションを定義できます。これにより、EISマップ・オブジェクトに問い合せてそれを変更する際に、TopLinkランタイムでは適切なEISインタラクションが使用されます。詳細は、「基本的な永続性操作用のカスタムEISインタラクションの構成」を参照してください。
また、TopLinkを使用して、読取り問合せおよびすべて読取り問合せのための名前付き問合せとしてインタラクションを定義することもできます。これらの問合せは、基本的な永続性操作の目的ではコールされません。これら追加の名前付き問合せは、特殊な目的のためにアプリケーション内からコールできます。詳細は、「名前付き問合せに関するEISインタラクションの作成」を参照してください。
問合せにおける例外は、ほとんどがデータベース操作の失敗によるデータベース例外です(「データベース例外(4002〜4018)」を参照)。書込み操作の場合は、オプティミスティック・ロックを使用するアプリケーションでの書込み、更新または削除操作で、OptimisticLockException
がスローされることもあります。これらの例外を捕捉するには、すべてのデータベース操作をtry
-catch
ブロック内で実行します。
try {
Vector employees = session.readAllObjects(Employee.class);
}
catch (DatabaseException exception) {
// handle exception
}
TopLinkアプリケーションの例外の詳細は、第14章「TopLink Workbenchエラー参照」を参照してください。
TopLinkでは、DataReadQuery
およびReadAllQuery
のすべてのサブクラスに対して、useCollectionClass
メソッドを用意しています。これらを使用して問合せを構成し、結果をCollection
またはMap
の具象インスタンスとして返すことができます。
コレクション問合せの結果の構成をマッピングのコンテナ・ポリシーと混同しないようにしてください(「コンテナ・ポリシーの構成」を参照)。これらの間には何の関係もありません。コレクション問合せの結果の構成により、TopLinkで特定の問合せから複数オブジェクトの結果を返す方法が決まります。マッピングのコンテナ・ポリシーは、ユーザーのドメイン・オブジェクトがコレクションを含むデータ・メンバーを実装する方法をTopLinkに指示します。
たとえば、クラスEmployee
とデータ・メンバーphoneNumbers
を考えてみます。Employee
のユーザー実装では、getPhoneNumbers
メソッドがVector
を返すとします。TopLink Workbenchを使用して、phoneNumbers
データ・メンバーを1対多のマッピングとしてマップします。マッピングのコンテナ・ポリシーを構成し、マッピングに、Vector
に格納されたデータ・メンバーの値(多数のPhoneNumber
オブジェクト)が含まれるようにします。これは、Employee
のユーザー実装に対応しています。
PhoneNumber
のDescriptorQueryManager
に対する、localPhoneNumbers
という名前のReadAllQuery
を定義します。localPhoneNumbers
問合せは、引数としてEmployee
オブジェクトのIDをとり、そのphoneNumbers
データ・メンバーから、市外局番が613の電話番号をすべて返します。
PhoneNumber
のDescriptorQueryManager
から、この名前付き問合せを取得します。このReadAllQuery
上で、useCollectionClass
メソッドをArrayList
クラスの引数付きでコールします。この問合せをEmployee
のID付きで実行します。この問合せは、Employee
オブジェクトのphoneNumbers
データ・メンバーから、市外局番が613のPhoneNumber
オブジェクトをすべて返します。この結果は、ArrayList
として返されます。
表94-2では、ReportQuery
が結果を返す方法を構成するために使用できるReportQuery
のメソッドをリストしています。
表94-2 レポート問合せの結果のオプション
メソッド | 問合せの戻り値 | 説明 |
---|---|---|
|
|
|
|
|
|
|
Object |
単一の値のみを返します。このオプションは、 |
詳細は、次を参照してください。