Force.com Apexの「Describe」でできること

1SOQLで全項目の値を取得(特定の子リレーションの値も同時に取得)

public class SOQLUtil {

   // 指定オブジェクトのみを取得対象とする
   public static String generateQueryString(String name) {

       // sObjectを生成
       sObject newObj = (sObject)Type.forName(name).newInstance();

       // 設定情報を取得
       Schema.DescribeSObjectResult descResult = newObj.getsObjectType().getDescribe();

       // 整形して戻す
       return 'Select ' + concatSet(descResult.fields.getMap().keySet(), ', ') + ' From ' + name;

   }
   
   // 指定オブジェクトと指定された子リレーションも取得対象とする
   public static String generateQueryString(String name, Set<String> childSet) {
       
       // sObjectを生成
       sObject newObj = (sObject)Type.forName(name).newInstance();

       // 設定情報を取得
       Schema.DescribeSObjectResult descResult = newObj.getsObjectType().getDescribe();
       
       // 取得用項目Set
       Set<String> targetSet = new Set<String>{concatSet(descResult.fields.getMap().keySet(), ', ')};
       
       // 子リレーションを取得
       for (Schema.ChildRelationship child : descResult.getChildRelationships()) {

           String rName = child.getRelationshipName();
           
           // 取得対象ではない場合、次へ
           if (!childSet.contains(rName)) continue;

           // 子リレーションの設定情報を取得
           Schema.DescribeSObjectResult childDesc = child.getChildSObject().getDescribe();
           
           Set<String> tempSet = getAllFieldsForChild(childDesc);
           
           targetSet.add('(Select ' + concatSet(tempSet, ', ') + ' From ' + rName + ')');

       }
       
       // 整形して戻す
       return 'Select ' + concatSet(targetSet, ', ') + ' From ' + name;

   }
   
   // 子リレーションの項目取得
   private static Set<String> getAllFieldsForChild(Schema.DescribeSObjectResult descResult) {

       Set<String> retSet = new Set<String>();

       Map<String, Schema.SObjectField> fieldMap = descResult.fields.getMap();

       for (String api : fieldMap.keySet()) {

           // 子リレーションでBase64は取得対象外
           if (fieldMap.get(api).getDescribe().getType() == Schema.DisplayType.base64) continue;

           retSet.add(api);

       }

       return retSet;

   }
   
   // 連結
   private static String concatSet(Set<String> strSet, String sep) {

       String retStr;

       for (String str : strSet) {

           retStr = retStr == null ? str : retStr + sep + str;

       }

       return retStr == null ? '' : retStr;

   }
}

コードサンプル(呼び出し側

String objectName = 'Account';

Set<String> childSet = new Set<String>{'Contacts', 'Cases'};

String query;

List<sObject> sojList;

// 対象オブジェクトの項目のみ
query = SOQLUtil.generateQueryString(objectName);

sojList = Database.query(query);

// 対象オブジェクトの項目と子リレーション
query = SOQLUtil.generateQueryString(objectName, childSet);

sojList = Database.query(query);

SOQLでは「Select *」を利用することはできませんが、「Describe」を利用して指定したオブジェクトの項目と子リレーションの項目を取得してSOQLで全ての項目の情報を取得することが可能です。
注意点:1SOQLで取得可能な子リレーション数は20個までとなりそれ以上指定するとエラーとなります。

describeSobject

項目セットの取得

コードサンプル

String query = 'Select Id';
for (Schema.FieldSetMember fsm : Account.sObjectType.getDescribe().fieldSets.getMap().get('DetailPage_FieldSet').getFields()) {
   query += ', ' + fsm.getFieldPath();
}
query += ' From Account ';
List<sObject> sojList = Database.query(query);

対象オブジェクトの項目セットからVisualforceページの表示に必要な項目を動的に取得してSOQLを発行することができます。また、オブジェクト名や項目セットも動的に指定できるようにするとより汎用性の高い処理が実現できます。

以下のように項目セットは「Describe」を利用しなくても取得可能です。

コードサンプル

Schema . FieldSet fs = Schema . SObjectType . Account . fieldSets . DetailPage_FieldSet ;
// または
Schema . FieldSet fs = Schema . SObjectType . Account . fieldSets . getMap ( ) . get ( 'DetailPage_FieldSet' ) ;

なお、Visualforceページでの項目セットの利用方法等については弊社佐竹によるエントリ「セールスフォースの項目セットを利用してメンテナンス性を高めよう」を参照してください。

取得したIDが期待しているオブジェクトのIDか確認

コードサンプル

public static Boolean isAccountId ( Id rid ) {
   return rid . startsWith ( Account . sObjectType . getDescribe ( ) . getKeyPrefix ( ) )
}

URLパラメータでIDの受け渡しを行うことも多いと思いますが、そのIDが目的のオブジェクトのIDであるか確認できます。
注意:一部オブジェクトにはPrefixがない場合もあります。

describeField

項目に対しても「getDescribe」メソッドが用意されていて項目の設定情報(API参照名、表示ラベル、文字数など)を取得することができます。
例えば以下の用途があります。

選択リスト値を動的に変更

コードサンプル

public Opportunity opp { get ; set ; }
public List getStageNameOptions ( ) {
   List retList = new List ( ) ;
   for ( Schema . PicklistEntry pe : Opportunity . StageName . getDescribe ( ) . getPicklistValues ( ) ) {
       if ( ! opp . IsJuchu__c & amp ; & amp ; pe . getLabel ( ) . startsWith ( '受注' ) ) {
           continue ;
       }
       // リスト値に追加
       retList . add ( new SelectOption ( pe . getValue ( ) , pe . getLabel ( ) ) ) ;
   }
   return retList ;
}

例では商談オブジェクトの受注チェックボックスがTRUEの場合のみ受注で始まるフェーズのみ選択リストで表示するようにしています。
注意点:1回のトランザクションで取得可能な選択リスト項目数は100個までです。(リスト値の数ではありません)

番外編

特定の「sObject」に対してのみ「Describe」を行う場合、以下のように簡単に行えます。

コードサンプル

Schema.DescribeSObjectResultdescR=Account.sObjectType.getDescribe();

また、オブジェクト名だけが文字列で取得できていて「Describe」を行いたい場合は以下のように先に「sObject」を解決してから「Describe」を行う必要があります。

コードサンプル

Schema . DescribeSObjectResult descR ;
String name = Account;
// パターン1(全部取得)
descR = Schema . getGlobalDescribe ( ) . get ( name ) . getDescribe ( ) ;
// パターン2(Typeを利用)
sObject newObj = ( sObject ) Type . forName ( name ) . newInstance ( ) ;
descR = newObj . getsObjectType ( ) . getDescribe ( ) ;
// パターン3(DaynamicSOQLの検索結果を利用)
sObject [ ] soList = Database . query ( 'Select Id From ‘ + name + ‘ Limit 1' ) ;
descR = soList . getsObjectType ( ) . getDescribe ( ) ;

どれを利用しても取得できる結果は同じになりますが、実行時間には若干の差異が出てきます。環境によりますが、私のDeveloperEditionではパターン2が最も早く続いてパターン3、パターン1(パターン2の約6倍)となりました。ただしパターン3は初回実行でパターン2の約5倍、2回目以降はパターン2より若干遅いくらいです。(ミリ秒の差ですのでそこまで大きく差異はないですが)

参照

https://developer.salesforce.com/docs/atlas.ja-jp.204.0.apexcode.meta/apexcode/apex_methods_system_sobject_describe.htm

http://appirio.co.jp/blog-category/tech-blog/force-com-apex%E3%81%AE%E3%80%8Cdescribe%E3%80%8D%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%93%E3%81%A8%EF%BC%88%E3%81%9D%E3%81%AE%EF%BC%92%EF%BC%89/

http://sfdcsrini.blogspot.com/2015/05/schemadescribesobjectresult-in-apex-and.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值