動的 DML
Describe Information を照会し、実行時に SOQL クエリの構築を行うことができます。さらに sObject を動的に作成し、DML を使用してそれらをデータベースに挿入することもできます。
指定されたデータ型の新規 sObject を作成するには、sObject トークンで newSObject メソッドを使用します。トークンは、具体的な sObject のデータ型 (Account など) にキャストする必要があります。次に例を示します。
1// Get a new account
2Account a = new Account();
3// Get the token for the account
4Schema.sObjectType tokenA = a.getSObjectType();
5// The following produces an error because the token is a generic sObject, not an Account
6// Account b = tokenA.newSObject();
7// The following works because the token is cast back into an Account
8Account b = (Account)tokenA.newSObject();sObject トークン tokenA は Account のトークンですが、別々にアクセスされるため sObject とみなされます。newSObject メソッドを使用するには、具体的な sObject のデータ型 Account にこのトークンを再度キャストする必要があります。割り当てについての詳細は、「クラスとキャスト」を参照してください。
newSObject で ID を指定して、既存のレコードを参照する sObject を作成し、後でそのレコードを更新することもできます。次に例を示します。
1SObject s = Database.query('SELECT Id FROM account LIMIT 1')[0].getSObjectType().
2 newSObject([SELECT Id FROM Account LIMIT 1][0].Id);「SObjectType クラス」を参照してください。
動的 sObject の作成例
この例では、Schema.getGlobalDescribe メソッドを介��て sObject トークンを取得し、その後、トークンに対して newSObject メソッドを使用して新しい sObject を作成する方法を示します。この例にも、取引先の動的作成を検証するテストメソッドが��まれます。
1public class DynamicSObjectCreation {
2 public static sObject createObject(String typeName) {
3 Schema.SObjectType targetType = Schema.getGlobalDescribe().get(typeName);
4 if (targetType == null) {
5 // throw an exception
6 }
7
8 // Instantiate an sObject with the type passed in as an argument
9 // at run time.
10 return targetType.newSObject();
11 }
12}1@isTest
2private class DynamicSObjectCreationTest {
3 static testmethod void testObjectCreation() {
4 String typeName = 'Account';
5 String acctName = 'Acme';
6
7 // Create a new sObject by passing the sObject type as an argument.
8 Account a = (Account)DynamicSObjectCreation.createObject(typeName);
9 System.assertEquals(typeName, String.valueOf(a.getSobjectType()));
10 // Set the account name and insert the account.
11 a.Name = acctName;
12 insert a;
13
14 // Verify the new sObject got inserted.
15 Account[] b = [SELECT Name from Account WHERE Name = :acctName];
16 system.assert(b.size() > 0);
17 }
18}項目値の設定と取得
String として表される API 参照名、または項目トークンのいずれかを使用している項目値を設定または取得するには、オブジェクトの get メソッドおよび put メソッドを使用します。次の例では、項目 AccountNumber の API 参照名が使用されます。
1SObject s = [SELECT AccountNumber FROM Account LIMIT 1];
2Object o = s.get('AccountNumber');
3s.put('AccountNumber', 'abc');次の例では、代わりに AccountNumber 項目のトークンを使用します。
1Schema.DescribeFieldResult dfr = Schema.sObjectType.Account.fields.AccountNumber;
2Sobject s = Database.query('SELECT AccountNumber FROM Account LIMIT 1');
3s.put(dfr.getsObjectField(), '12345');Object スカラーデータ型は、sObject の項目値を設定または取得するために、汎用データ型として使用できます。これは、anyType 項目のデータ型と同等です。Object データ型は、sObject の汎用型として使用可能な sObject データ型とは異なります。
外部キーの設定と取得
Apex は、API と同じ方法で、名前 (または外部 ID) による外部キーの入力をサポートします。外部キーのスカラー ID 値を設定または取得するには、get メソッドまたは put メソッドを使用します。
外部キーに関連付けられた���コードを設定または取得するには、getSObject メソッドと putSObject メソッドを使用します。これらのメソッドは、Object データ型ではなく sObject データ型で使用される必要があります。次に例を示します。
1SObject c =
2 Database.query('SELECT Id, FirstName, AccountId, Account.Name FROM Contact LIMIT 1');
3SObject a = c.getSObject('Account');子 sObject を使用しているときに親 sObject 値の外部 ID を指定する必要はありません。親 sObject に ID を提供した場合、DML 操作によって無視されます。Apex は、常に入力した ID で親オブジェクトを返すリレーション SOQL クエリを介して、外部キーが入力されることを前提としています。ID がない場合、子オブジェクトに使用します。
たとえば、カスタムオブジェクト C1 に、親カスタムオブジェクト C2 にリンクする外部キー C2__c があるとします。C1 オブジェクトを作成し、値 C2__r が割り当てられた「AW Computing」という名前の C2 レコードに関連付けるとします。親から子へのリレーションを介して入力されるため、「AW Computing」レコードの ID は不要です。次に例を示します。
1insert new C1__c(Name = 'x', C2__r = new C2__c(Name = 'AW Computing'));C2__r の ID に値を割り当てている場合、その値は無視されます。ID がない場合、レコードではなくオブジェクト (C2__c) に割り当てます。
1String queryString = 'SELECT Id, Name, ' +
2 '(SELECT FirstName, LastName FROM Contacts LIMIT 1) FROM Account';
3SObject[] queryParentObject = Database.query(queryString);
4
5for (SObject parentRecord : queryParentObject){
6 Object ParentFieldValue = parentRecord.get('Name');
7 // Prevent a null relationship from being accessed
8 SObject[] childRecordsFromParent = parentRecord.getSObjects('Contacts');
9 if (childRecordsFromParent != null) {
10 for (SObject childRecord : childRecordsFromParent){
11 Object ChildFieldValue1 = childRecord.get('FirstName');
12 Object ChildFieldValue2 = childRecord.get('LastName');
13 System.debug('Account Name: ' + ParentFieldValue +
14 '. Contact Name: '+ ChildFieldValue1 + ' ' + ChildFieldValue2);
15 }
16 }
17}