在JSF和Richfaces的官方示例里面沒發(fā)現(xiàn)正經(jīng)的數(shù)據(jù)庫分頁示例,于是自己輪了一個(gè),還算比較滿意,分享出來。
struts等框架,視圖(jsp、freemarker等)直接獲取action中準(zhǔn)備好的數(shù)據(jù)結(jié)果集合,請(qǐng)求下一頁數(shù)據(jù)的時(shí)候,同樣后臺(tái)action處理請(qǐng)求,把a(bǔ)ction中的數(shù)據(jù)集合用新的這一頁數(shù)據(jù)替換掉,然后渲染頁面,從而實(shí)現(xiàn)分頁。每次請(qǐng)求action的處理過程可以拿到頁號(hào)等信息,所以在action調(diào)用service的時(shí)候就可以使用這些信息,調(diào)用相應(yīng)的方法做分頁數(shù)據(jù)查詢。
JSF結(jié)合Richfaces做這個(gè)事情和Struts等框架有有很大的區(qū)別。
rich:dataTable這個(gè)標(biāo)記可以配合一個(gè)rich:dataScroller使用,達(dá)到ajax翻頁的效果,但是這時(shí)候dataTable的value實(shí)際上要求是一個(gè)ExtendedDataModel對(duì)象。每次翻頁的時(shí)候,頁面組件調(diào)用這個(gè)ExtendedDataModel對(duì)象的walk方法獲取目標(biāo)頁的數(shù)據(jù)——注意這個(gè)過程是不經(jīng)過Action的。也就是說,頁面第一次加載的時(shí)候,dataTable的value屬性是#{action.data},其中data屬性是一個(gè)ExtendedDataModel對(duì)象,此后翻頁的過程中,不再經(jīng)過action。
基于這樣的不同,需要采用一種新的機(jī)制來實(shí)現(xiàn)數(shù)據(jù)查詢過程。action返回給視圖的data對(duì)象,不應(yīng)該是查詢出來的某一頁的一個(gè)數(shù)據(jù)集合,而是一種查詢數(shù)據(jù)的能力。
最終Action中的代碼如下:
findPage返回的是一個(gè)PagedDataMode(繼承ExtendedDataModel),其中包含了真正的查詢數(shù)據(jù)的能力:DataProvider。
DataProvider很簡單:
PagedDataMode稍微復(fù)雜一點(diǎn),其中做了一下數(shù)據(jù)緩存:
struts等框架,視圖(jsp、freemarker等)直接獲取action中準(zhǔn)備好的數(shù)據(jù)結(jié)果集合,請(qǐng)求下一頁數(shù)據(jù)的時(shí)候,同樣后臺(tái)action處理請(qǐng)求,把a(bǔ)ction中的數(shù)據(jù)集合用新的這一頁數(shù)據(jù)替換掉,然后渲染頁面,從而實(shí)現(xiàn)分頁。每次請(qǐng)求action的處理過程可以拿到頁號(hào)等信息,所以在action調(diào)用service的時(shí)候就可以使用這些信息,調(diào)用相應(yīng)的方法做分頁數(shù)據(jù)查詢。
JSF結(jié)合Richfaces做這個(gè)事情和Struts等框架有有很大的區(qū)別。
rich:dataTable這個(gè)標(biāo)記可以配合一個(gè)rich:dataScroller使用,達(dá)到ajax翻頁的效果,但是這時(shí)候dataTable的value實(shí)際上要求是一個(gè)ExtendedDataModel對(duì)象。每次翻頁的時(shí)候,頁面組件調(diào)用這個(gè)ExtendedDataModel對(duì)象的walk方法獲取目標(biāo)頁的數(shù)據(jù)——注意這個(gè)過程是不經(jīng)過Action的。也就是說,頁面第一次加載的時(shí)候,dataTable的value屬性是#{action.data},其中data屬性是一個(gè)ExtendedDataModel對(duì)象,此后翻頁的過程中,不再經(jīng)過action。
基于這樣的不同,需要采用一種新的機(jī)制來實(shí)現(xiàn)數(shù)據(jù)查詢過程。action返回給視圖的data對(duì)象,不應(yīng)該是查詢出來的某一頁的一個(gè)數(shù)據(jù)集合,而是一種查詢數(shù)據(jù)的能力。
最終Action中的代碼如下:
1 public class CommonAction{
2
3 protected PagedDataModel data; //用于列表展現(xiàn)的數(shù)據(jù)
4
5 @PostConstruct
6 public void init(){
7 Map<String,Object> parameters =
;//查詢條件
8 this.data = this.findPage(parameters);
9 }
10
11 /**
12 * 使用Service分頁查詢數(shù)據(jù)
13 * @return
14 * 注意,由于JSF的結(jié)構(gòu),這里返回的其實(shí)并不是真正的查詢結(jié)果,而是一種查詢數(shù)據(jù)的能力。
15 * 這種能力返回給JSF的頁面組件作為value,頁面渲染的時(shí)候使用這個(gè)能力來獲取數(shù)據(jù)
16 */
17 protected PagedDataModel findPage(final Map<String,Object> parameters) {
18 int count = this.getService().count(propertyFilterList).intValue();
19 return new PagedDataModel(count, new DataProvider(){
20
21 @Override
22 public List<?> getList(int firstRow, int maxResults) {
23 return CommonAction.this.getService().find(parameters, firstRow, maxResults);
24 }
25 });
26 }
27 }
2
3 protected PagedDataModel data; //用于列表展現(xiàn)的數(shù)據(jù)
4
5 @PostConstruct
6 public void init(){
7 Map<String,Object> parameters =


8 this.data = this.findPage(parameters);
9 }
10
11 /**
12 * 使用Service分頁查詢數(shù)據(jù)
13 * @return
14 * 注意,由于JSF的結(jié)構(gòu),這里返回的其實(shí)并不是真正的查詢結(jié)果,而是一種查詢數(shù)據(jù)的能力。
15 * 這種能力返回給JSF的頁面組件作為value,頁面渲染的時(shí)候使用這個(gè)能力來獲取數(shù)據(jù)
16 */
17 protected PagedDataModel findPage(final Map<String,Object> parameters) {
18 int count = this.getService().count(propertyFilterList).intValue();
19 return new PagedDataModel(count, new DataProvider(){
20
21 @Override
22 public List<?> getList(int firstRow, int maxResults) {
23 return CommonAction.this.getService().find(parameters, firstRow, maxResults);
24 }
25 });
26 }
27 }
findPage返回的是一個(gè)PagedDataMode(繼承ExtendedDataModel),其中包含了真正的查詢數(shù)據(jù)的能力:DataProvider。
DataProvider很簡單:
1 public interface DataProvider {
2
3 List<?> getList(int firstRow, int maxResults);
4
5 }
2
3 List<?> getList(int firstRow, int maxResults);
4
5 }
PagedDataMode稍微復(fù)雜一點(diǎn),其中做了一下數(shù)據(jù)緩存:
1 /**
2 *
3 * 分頁數(shù)據(jù)模型,用于rich:dataTable
4 *
5 * @author allan
6 *
8 */
9 public class PagedDataModel extends ExtendedDataModel {
10 private Integer currentId;
11 private Map<Integer, Object> dataMap = new LinkedHashMap<Integer, Object>();
12 protected Integer count;
13 private int lastFirstRow = 0;
14 private int lastMaxResults = 0;
15 private SortProperties sortFields;
16
17 private DataProvider dataProvider;
18
19 public PagedDataModel(int count,DataProvider dataProvider){
20 super();
21 super.count = count;
22 this.dataProvider = dataProvider;
23 }
24
25 /**
26 * 最終獲取總記錄數(shù)的方法
27 * @return
28 */
29 public int getCount() {
30 return super.count;
31 }
32
33 /**
34 * 最終獲取數(shù)據(jù)的方法
35 * @param firstRow
36 * @param maxResults
37 * @return
38 */
39 public List<?> getList(int firstRow, int maxResults, SortProperties sortFields) {
40 return this.dataProvider.getList(firstRow, maxResults, sortFields);
41 }
42
43
44 @Override
45 public Object getRowKey() {
46 return this.currentId;
47 }
48
49 @Override
50 public void setRowKey(Object key) {
51 this.currentId = (Integer) key;
52 }
53
54 @Override
55 public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException {
56 int firstRow = ((SequenceRange) range).getFirstRow();
57 int maxResults = ((SequenceRange) range).getRows();
58 if(maxResults <= 0) maxResults = Integer.MAX_VALUE;
59 //數(shù)據(jù)是不存在
60 if(firstRow != this.lastFirstRow || maxResults != this.lastMaxResults) {
61 //獲取所需數(shù)據(jù)
62 List<?> listRow = this.getList(firstRow, maxResults, this.sortFields);
63 //記錄數(shù)據(jù)
64 dataMap.clear();
65 for(int i = 0; i < listRow.size(); i++) {
66 Object row = listRow.get(i);
67 int index = firstRow + i;
68 dataMap.put(index, row);
69 }
70
71 this.lastFirstRow = firstRow;
72 this.lastMaxResults = maxResults;
73 }
74 //設(shè)置數(shù)據(jù)
75 for(Integer index : dataMap.keySet()) {
76 visitor.process(context, index, argument);
77 }
78 }
79
80 @Override
81 public int getRowCount() {
82 if(count == null)
83 count = this.getCount();
84 return count;
85 }
86
87 @Override
88 public boolean isRowAvailable() {
89 if(dataMap == null) {
90 return false;
91 } else {
92 return dataMap.containsKey(currentId);
93 }
94 }
95
96 @Override
97 public Object getRowData() {
98 return dataMap.get(currentId);
99 }
100
101 @Override
102 public Object getWrappedData() {
103 return this.getList(0, Integer.MAX_VALUE, this.sortFields);
104 }
105
106 @Override
107 public void setWrappedData(Object arg0) {
108 throw new UnsupportedOperationException();
109 }
110
111 @Override
112 public int getRowIndex() {
113 throw new UnsupportedOperationException();
114 }
115
116 @Override
117 public void setRowIndex(int arg0) {
118 throw new UnsupportedOperationException();
119 }
120 }
121
2 *
3 * 分頁數(shù)據(jù)模型,用于rich:dataTable
4 *
5 * @author allan
6 *
8 */
9 public class PagedDataModel extends ExtendedDataModel {
10 private Integer currentId;
11 private Map<Integer, Object> dataMap = new LinkedHashMap<Integer, Object>();
12 protected Integer count;
13 private int lastFirstRow = 0;
14 private int lastMaxResults = 0;
15 private SortProperties sortFields;
16
17 private DataProvider dataProvider;
18
19 public PagedDataModel(int count,DataProvider dataProvider){
20 super();
21 super.count = count;
22 this.dataProvider = dataProvider;
23 }
24
25 /**
26 * 最終獲取總記錄數(shù)的方法
27 * @return
28 */
29 public int getCount() {
30 return super.count;
31 }
32
33 /**
34 * 最終獲取數(shù)據(jù)的方法
35 * @param firstRow
36 * @param maxResults
37 * @return
38 */
39 public List<?> getList(int firstRow, int maxResults, SortProperties sortFields) {
40 return this.dataProvider.getList(firstRow, maxResults, sortFields);
41 }
42
43
44 @Override
45 public Object getRowKey() {
46 return this.currentId;
47 }
48
49 @Override
50 public void setRowKey(Object key) {
51 this.currentId = (Integer) key;
52 }
53
54 @Override
55 public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException {
56 int firstRow = ((SequenceRange) range).getFirstRow();
57 int maxResults = ((SequenceRange) range).getRows();
58 if(maxResults <= 0) maxResults = Integer.MAX_VALUE;
59 //數(shù)據(jù)是不存在
60 if(firstRow != this.lastFirstRow || maxResults != this.lastMaxResults) {
61 //獲取所需數(shù)據(jù)
62 List<?> listRow = this.getList(firstRow, maxResults, this.sortFields);
63 //記錄數(shù)據(jù)
64 dataMap.clear();
65 for(int i = 0; i < listRow.size(); i++) {
66 Object row = listRow.get(i);
67 int index = firstRow + i;
68 dataMap.put(index, row);
69 }
70
71 this.lastFirstRow = firstRow;
72 this.lastMaxResults = maxResults;
73 }
74 //設(shè)置數(shù)據(jù)
75 for(Integer index : dataMap.keySet()) {
76 visitor.process(context, index, argument);
77 }
78 }
79
80 @Override
81 public int getRowCount() {
82 if(count == null)
83 count = this.getCount();
84 return count;
85 }
86
87 @Override
88 public boolean isRowAvailable() {
89 if(dataMap == null) {
90 return false;
91 } else {
92 return dataMap.containsKey(currentId);
93 }
94 }
95
96 @Override
97 public Object getRowData() {
98 return dataMap.get(currentId);
99 }
100
101 @Override
102 public Object getWrappedData() {
103 return this.getList(0, Integer.MAX_VALUE, this.sortFields);
104 }
105
106 @Override
107 public void setWrappedData(Object arg0) {
108 throw new UnsupportedOperationException();
109 }
110
111 @Override
112 public int getRowIndex() {
113 throw new UnsupportedOperationException();
114 }
115
116 @Override
117 public void setRowIndex(int arg0) {
118 throw new UnsupportedOperationException();
119 }
120 }
121