【Salesforce】transientのリストから取得したレコードについて

【Salesforce】transientのリストから取得したレコードについて

先日実装したVisualforceのページで、transientをつけた変数がありました。

その変数を使った処理を行った際に、予想と違った動作をしたところがあったのでメモです。

transient修飾子をつけた変数はビューステートを残さないため、サーバー側に保持されません

https://developer.salesforce.com/docs/atlas.ja-jp.206.0.apexcode.meta/apexcode/apex_classes_keywords_transient.htm

transientをつけたリストに入れた値は保持されないのですが、別の変数に移すと保持されるようです。

実験に使用したページのコントローラ側です。

public class TransientPageController{

    transient public List<Account> accountList{get;set;}
    public List<Account> copyAccountList{get;set;}
    public List<Contact> copyContactList{get;set;}
    public Map<Id, List<Contact>> accountContactsMap{get;set;}
    
    /** */
    public TransientPageController(){
    
        this.accountList = new List<Account>();
        this.copyAccountList = new List<Account>();
        this.copyContactList = new List<Contact>();
        this.accountContactsMap = new Map<Id, List<Contact>>();
    }
    
    /**
     * レコードを取得する
     */
    public void init(){
    
        // 取引先リストを取得する
        this.accountList = [select Id, Name, (select Id, Name from Contacts) from Account where Id in (select AccountId from Contact)];
        // コピーする
        this.copyAccountList = this.accountList;
        
        // 取引先責任者のリストを作成する
        this.copyContactList = new List<Contact>();
        // 取引先-取引責任者リストのMapを作成する
        this.accountContactsMap = new Map<Id, List<Contact>>();
        for(Account acc : this.accountList){
        
            this.copyContactList.addAll(acc.Contacts);
            this.accountContactsMap.put(acc.Id, acc.Contacts);
        }

        system.debug('【ログ】accountList:' + this.accountList);
        system.debug('【ログ】copyAccountList:' + this.copyAccountList);
        system.debug('【ログ】copyContactList:' + this.copyContactList);
        system.debug('【ログ】accountContactsMap:' + this.accountContactsMap);
    }
    
    /**
     * コントローラからの呼び出し用
     */
    public void refresh(){
    
        system.debug('【ログ】accountList:' + this.accountList);
        system.debug('【ログ】copyAccountList:' + this.copyAccountList);
        system.debug('【ログ】copyContactList:' + this.copyContactList);
        system.debug('【ログ】accountContactsMap:' + this.accountContactsMap);
    }
}

こちらはページ側です。

取得した取引先リストと紐づく取引先責任者リストを表示しています。

更新ボタンを押すと、サーバー側で特に何もしない処理を呼び出します。

<apex:page id="Page"
 controller="TransientPageController"
 action="{!init}">

  <apex:form id="Form" >

    <apex:commandButton action="{!refresh}" value="更新" />

    <div style="margin-top: 20px; border-bottom: solid #ccc 1px;">
      <div style="display: inline-block; width: 30%;">
        <apex:outputText value="取引先" />
      </div>
      <div style="display: inline-block; width: 30%;">
        <div>
          <apex:outputText value="取引先責任者" />
        </div>
      </div>
    </div>

    <apex:repeat value="{!accountList}" var="acc" rendered="{!accountList != null}" >
      <div style=" margin-top: 20px;  border-bottom: solid #ccc 1px;">
        <div style="display: inline-block; width: 30%;">
          <apex:outputText value="{!acc.Name}" />
        </div>
        <div style="display: inline-block; width: 30%;">
          <apex:repeat value="{!accountContactsMap[acc.Id]}" var="contact" >
            <div>
              <apex:outputText value="{!contact.Name}" />
            </div>
          </apex:repeat>
        </div>
      </div>
    </apex:repeat>

  </apex:form>

</apex:page>

initで取得した値と更新を押したときの値を比較します。

transientに指定したaccountListから取得されたレコードはすべて消えてしまうと思っていました。

結果としては、こうなりました。

transientにした変数以外は値が保持されていることがわかります。

ということで、transientにした変数から別の変数に移したレコードは消えずに残っていることが分かりました。

ビューステートが危ないときは気を付けなければいけませんね。

変数名 コンストラクタ 更新後
accountList 値あり null
copyAccountList 値あり 値あり
copyContactList 値あり 値あり
accountContactsMap 値あり 値あり

No comments.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です