【Apex+Visualforce】DML currently not allowed. コンストラクタでDMLの実行はできない。

Salesforce

初期表示時にオブジェクトのレコードをupdateする画面を作ったら、update実行のところでエラーが発生。

DML currently not allowed

結論から言うと、ControllerクラスのコンストラクタでDMLの実行はできないらしい
対策としては、初期表示アクションを作って、apex:pageタグのactionで指定してあげればいい。

詳しく書いていきますね。

エラーとなるソース

まずはエラーとなってしまうソース。
初期表示時に取引先の判定処理(ここでは詳しく触れませんが)を行い、結果を画面に表示することを期待しています。
判定が正常に行われた場合はChecked__cという項目をtrueにしてupdateします。

visualforceページ

<apex:page controller="AccountCheckController">
    <apex:outputText value="{! msg }" />
</apex:page>

Controllerクラス

public class AccountCheckController {

    /** 取引先ID */
    public String accountId;
    
    /** メッセージ */
    public String msg{get; set;}
    
    /**
     * コンストラクタ.
     */
    public AccountCheckController() {
	    Map<String, String> paramMap = ApexPages.currentPage().getParameters();
        this.accountId = paramMap.get('id');
        
        // 取引先取得
        List<Account> accountList = [SELECT Id, Name, Checked__c FROM Account WHERE Id =: this.accountId];
        if (accountList.size() == 0) {
            this.msg = 'エラー:取引先が取得できませんでした。';
			return;
        }
        Account acc = accountList.get(0);
        
        // 判定処理
        AccountCheck accountCheck = new AccountCheck();
        boolean result = accountCheck.exec();
        if (!result) {
            this.msg = 'エラー:判定処理でエラーが発生しました。';
            return;
        }
        
        // 判定処理が正常の場合、チェック実施済フラグを立てる
        acc.Checked__c = true;
        update acc;
        
        this.msg = '判定処理が完了しました!';
    }
}

この画面を表示すると、”DML currently not allowed”のエラーが発生します。
DMLを実行している箇所(34行目)でエラーになる。

エラーとならないよう修正

ControllerクラスのコンストラクタでDMLの実行はできないので、初期表示で処理するアクションメソッドを作成して、それをapex:pageタグのactionで指定してあげます。
以下のような感じ。変更箇所はハイライトしてます。

visualforceページ

<apex:page controller="AccountCheckController" action="{! init }">
    <apex:outputText value="{! msg }" />
</apex:page>

Controllerクラス

public class AccountCheckController {

    /** 取引先ID */
    public String accountId;
    
    /** メッセージ */
    public String msg{get; set;}
    
    /**
     * 初期表示処理.
     */
    public void init() {
	    Map<String, String> paramMap = ApexPages.currentPage().getParameters();
        this.accountId = paramMap.get('id');
        
        // 取引先取得
        List<Account> accountList = [SELECT Id, Name, Checked__c FROM Account WHERE Id =: this.accountId];
        if (accountList.size() == 0) {
            this.msg = 'エラー:取引先が取得できませんでした。';
			return;
        }
        Account acc = accountList.get(0);
        
        // 判定処理
        AccountCheck accountCheck = new AccountCheck();
        boolean result = accountCheck.exec();
        if (!result) {
            this.msg = 'エラー:判定処理でエラーが発生しました。';
            return;
        }
        
        // 判定処理が正常の場合、チェック実施済フラグを立てる
        acc.Checked__c = true;
        update acc;
        
        this.msg = '判定処理が完了しました!';
    }
}

コメント

タイトルとURLをコピーしました