ページング使ってパフォーマンス改善 part2

スポンサーリンク

前回のページング手法は…

StandardSetControllerを使ったページングについては、こちらで紹介しました。
ただし、リスト表示は読み取り専用で、インライン編集でテキスト入力する場合には向いていませんでした。
今回はインライン編集する場合のページング実装方法について記載します。

今回はOFFSETを使う

インライン編集を伴うリストのページングにはSOQLのオフセットを使用します。
OFFSETはSOQLの実行結果を指定された分ずらすことができ、ページ切り替えの時にこのオフセット位置をページに合わせて変えていくことで、リストの表示を変えることができます。

OFFSETのイメージはこんな感じです。

OFFSET有無のSOQL

使い方は、SOQLのLimitの後に、Offset句をつけるだけです。
Limitはなくても構いませんが、セットで使用することを推奨します。

Select Id, Name From Account Limit 100 Offset 100

実装例

では、実際のページング処理を入れた使用例、今回は取引先対象でページサイズを100とした時の取引先名のインライン編集を可能としたページングを作成していきます。

まずは、Apexクラス(コントローラー)から
PagingCtrl2.cls

public class PagingCtrl2 {
    // 1ページあたりの表示件数
    private static final Integer PAGE_SIZE = 100;
    // 現在選択中のページ
    public Integer currentPage {get; private set;}
    // ページ数
    public Integer totalPage {get; private set;}
    // 前へボタンが有効か
    public Boolean enablePrev {get; private set;}
    // 次へボタンが有効か
    public Boolean enableNext {get; private set;}
    // 現ページのリスト
    public List<Account> accountList {get; set;}

    // コンストラクタ
    public PagingCtrl2(){
    }
    
    // 初期アクション
    public PageReference init() {
        currentPage = 1;
        refreshRecords();
        return null;
    }
    
    // 前へボタンクリックアクション
    public void prev() {
        // ページ数を1減らす
        currentPage = currentPage - 1;
        refreshRecords();
    }
    
    // 次へボタンクリックアクション
    public void next() {
        // ページ数を1増やす
        currentPage = currentPage + 1;
        refreshRecords();
    }
    
    // セーブ時のアクション
    public PageReference save() {
        update accountList;
        
        // ページ数を1に戻して、更新のメッセージを出す
        currentPage = 1;
        refreshRecords();
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, '取引先名の更新が完了しました', 'detail - info'));
        return null;
    }

    // 現ページのレコードを取得
    private void refreshRecords(){
        // トータルのレコード数を算出
        Integer totalRecords = [Select Count() From Account];
        // ページ数に応じてオフセット数を調整
        Integer offsetNum = (currentPage - 1) * PAGE_SIZE;
        // 前へボタンは現ページが1ページ目の時に可能
        enablePrev = currentPage != 1;
        // 次へボタンが押せるかどうかの判定
        enableNext = (currentPage * PAGE_SIZE) < totalRecords;
        // トータルのレコード数からページ数を割り出す
        totalPage = (totalRecords + PAGE_SIZE - 1)/ PAGE_SIZE;
        
        // オフセット位置を考慮してレコード取得
        accountList = [Select Id, Name From Account Limit :PAGE_SIZE OFFSET :offsetNum];
    }
}

ポイントは、ページ数に応じて、オフセット位置を変えているところですかね。

次にVisualForceページ
AccountPaging2.cls

<apex:page controller="PagingCtrl2" action="{!init}" >
    <apex:pageMessages />
        <apex:form >
        <apex:pageBlock >
            <!-- ページネーション -->
            <apex:pageBlockButtons >
                <apex:outputPanel layout="none" rendered="{!enablePrev}">
                    <apex:commandLink value="< 前" action="{!prev}" />
                    <apex:outputLabel value=" | " />
                </apex:outputPanel>
                <apex:outputLabel value="{!currentPage}/{!totalPage}" />
                <apex:outputPanel layout="none" rendered="{!enableNext}">
                    <apex:outputLabel value=" | " />
                    <apex:commandLink value="次 >" action="{!next}" />
                </apex:outputPanel>
                <apex:commandButton action="{!save}" value="Save" />
            </apex:pageBlockButtons>
            <!-- ページサイズ分のリストを表示 -->
            <apex:pageBlockTable value="{!AccountList}" var="acc">
                <apex:column >
                    <apex:inputField value="{!acc.Name}"/>
                </apex:column>
            </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
</apex:page>

それで、画面表示はこんな感じになります。

Visualforceのページング処理

今回は簡潔な画面でしたが、実際はページングした時に入力内容を保持したりとか、変更した部分だけをupdateするような差分管理が必要だったりします。
そうなると、結構複雑で、ガバナやビューステートなどとの制限との戦いになるので、この辺躓かないように留意しましょう。

まとめ

  • OffsetはSOQLの実行結果のリストを指定数分ずらすことができる
  • ページング処理を使用する場合は、Limitとセットで使用する

コメント