テーブルのスコープ
今回は
【概要】
コーディングの仕方によってはうまく動かないことがあります。
今回は一覧ページからデータを選択して、
詳細ページに遷移するというサンプルを作ります。
サンプルを実行する際入り口となるページからアクセスします。
入り口となるページのソースは↓になります。
ファイル名は「dataTableIndex.xhtml」です。
<?xml version="1.0" encoding="Windows-31J" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> <f:view> <h:head> <meta http-equiv="Content-Type" content="text/html; charset=Windows-31J" /> <title>データテーブル</title> </h:head> <h:body> <h:form id="sampleForm"> <h:commandLink value="GO" action="#{dataTableSample.init()}" /> </h:form> </h:body> </f:view> </html>
【上手くいかないコード】
[一覧ページ]
まずは一覧ページからです。
ManagedBeanのソースです。
@ManagedBean(name = "dataTableSample") @RequestScoped public class DataTableSample { private List<DataBean> dataList = null; public String init() { dataList = new ArrayList<>(); dataList.add(new DataBean("CODE-001", "えんぴつ", 100)); dataList.add(new DataBean("CODE-002", "けしごむ", 50)); dataList.add(new DataBean("CODE-003", "ノート", 200)); return "dataTableSample.xhtml"; } // アクセサメソッドは省略 }
このManagedBeanはリクエストスコープで作成しています。
一覧を表示するためのinitメソッドを作成します。
initメソッドは概要で作成したXHTMLから実行されます。
一覧表示用のBeanを作成した後は一覧ページに遷移します。
つづいて、XHTMLのソースです。
ファイル名は「dataTableSample.xhtml」です。
<?xml version="1.0" encoding="Windows-31J" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> <f:view> <h:head> <meta http-equiv="Content-Type" content="text/html; charset=Windows-31J" /> <title>データテーブル</title> </h:head> <h:body> <h:form id="sampleForm"> <h:dataTable var="recordData" value="#{dataTableSample.dataList}" border="1" cellspacing="0"> <h:column> <f:facet name="header"> コード </f:facet> <h:commandLink value="#{recordData.code}" action="#{dataTableScope.init(recordData.code, recordData.name, recordData.price)}" /> </h:column> <h:column> <f:facet name="header"> 商品名 </f:facet> <h:outputText value="#{recordData.name}" /> </h:column> <h:column> <f:facet name="header"> 価格 </f:facet> <h:outputText value="#{recordData.price}" /> <f:facet name="footer"> 価格フッター </f:facet> </h:column> </h:dataTable> </h:form> </h:body> </f:view> </html>
前回のサンプルをベースに作っています。
initメソッドを呼び出しています。
initメソッドには各レコードのデータをパラメータとして受け取ります。
[詳細ページ]
次に詳細ページです。
ManagedBeanのソースです。
@ManagedBean(name = "dataTableScope") @RequestScoped public class DataTableScopeSample { private String code = null; private String name = null; private Integer price = null; public String init(final String code, final String name, final Integer price) { this.code = code; this.name = name; this.price = price; return "dataTableScope.xhtml"; } // アクセサメソッドは省略 }
initメソッドは一覧からリンクをクリックした時に実行されるメソッドです。
受け取ったパラメータを自分自身に設定して、
詳細ページに遷移させています。
つづいてXHTMLのソースです。
ファイル名は「dataTableScope.xhtml」です。
<?xml version="1.0" encoding="Windows-31J" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> <f:view> <h:head> <meta http-equiv="Content-Type" content="text/html; charset=Windows-31J" /> <title>データテーブル</title> </h:head> <h:body> <h:form id="sampleForm"> <div> <h:outputText value="コード:" /> <h:outputText value="#{dataTableScope.code}" /> </div> <div> <h:outputText value="商品名:" /> <h:outputText value="#{dataTableScope.name}" /> </div> <div> <h:outputText value="価格:" /> <h:outputText value="#{dataTableScope.price}" /> </div> </h:form> </h:body> </f:view> </html>
DataTableScopeSampleのデータを表示しているだけのページです。
【改善方法 その1 スコープを変えてみる】
[直してみる]
ManagedBeanのスコープを
リクエストスコープからセッションスコープに変えてみます。
@ManagedBean(name = "dataTableSample") @SessionScoped public class DataTableSample implements Serializable { private static final long serialVersionUID = -5247838625597831733L; private List<DataBean> dataList = null; public String init() { dataList = new ArrayList<>(); dataList.add(new DataBean("CODE-001", "えんぴつ", 100)); dataList.add(new DataBean("CODE-002", "けしごむ", 50)); dataList.add(new DataBean("CODE-003", "ノート", 200)); return "dataTableSample.xhtml"; } // アクセサメソッドは省略 }
[デメリット]
セッションスコープにしてしまうとBeanのListを全て
セッションで持つことになるということです。
件数が多かったり、一覧画面が多かったりすると
セッションによりメモリが食いつぶされてしまいます。
セッションスコープを使う場合、件数を減らすなどの工夫が必要になります。
【改善方法 その2 データ取得のタイミングを変えてみる】
[直してみる]
一覧データの取得のタイミングをinitメソッドから、
コンストラクタに移動してみます。
@ManagedBean(name = "dataTableSample") @RequestScoped public class DataTableSample { private List<DataBean> dataList = null; public DataTableSample() { dataList = new ArrayList<>(); dataList.add(new DataBean("CODE-001", "えんぴつ", 100)); dataList.add(new DataBean("CODE-002", "けしごむ", 50)); dataList.add(new DataBean("CODE-003", "ノート", 200)); } public String init() { return "dataTableSample.xhtml"; } // アクセサメソッドは省略 }
[デメリット]
リクエストスコープなのでメモリの食いつぶしについては
セッションスコープより心配しなくても良くなりました。
しかし、一覧から詳細に遷移するときも
コンストラクタが呼ばれてしまいます。
そのため、不要な処理が実行されてしまいます。