使用延迟加载在动态填充的数据表中排序
Sorting in an dynamically filled Datatable with lazy loading
我的延迟加载数据有问题table。
首先,这里的代码:
<p:tabView>
<!-- Tabs A and B, working fine -->
<p:tab title="C">
<p:commandButton value="get C" id="openC" actionListener="#{backingBean.initC}" render="cTable" update="cTable"></p:commandButton>
<p:separator/>
<p:dataTable id="cTable" var="cTable" value="#{backingBean.lazyC}" paginator="true"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="5,10,15" rows="10" sortMode="multiple" lazy="true" rendered="#{backingBean.cAvailable}">
<c:forEach var="colC" items="#{backingBean.headerAllocationC}">
<p:column headerText="#{colC.header}" sortBy="#{cTable[colC.property]}">
<div align="center">
<h:outputText value="#{cTable[colC.property]}"></h:outputText>
</div>
</p:column>
</c:forEach>
</p:dataTable>
</p:tab>
</p:tabView>
遵循我的惰性数据模型的排序方法:
@Override
public List<cBean> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String,Object> filters){
List<cBean> data = new ArrayList<cBean>();
if (multiSortMeta != null) {
for (SortMeta sortMeta : multiSortMeta) {
System.out.println("SORTFIELD:" +sortMeta.getSortField());
System.out.println("SORTORDER:" +sortMeta.getSortOrder());
//System.out.println("SORTFUNCTION:"+sortMeta.getSortFunction());
System.out.println("COLUMN:" +sortMeta.getColumn());
System.out.println("CLASS:" +sortMeta.getClass());
}
}
for (cBean c : datasource) {
boolean match = true;
if (filters != null) {
for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
try {
String filterProperty = it.next();
Object filterValue = filters.get(filterProperty);
String fieldValue = String.valueOf(c.getClass().getField(filterProperty).get(c));
if (filterValue == null || fieldValue.startsWith(filterValue.toString())) {
match = true;
}
else {
match = false;
continue;
}
} catch (Exception e) {
match = false;
}
}
}
if (match) {
data.add(c);
}
}
int dataSize = data.size();
this.setRowCount(dataSize);
if (dataSize > pageSize) {
try {
return data.subList(first, first+pageSize);
} catch (IndexOutOfBoundsException e) {
return data.subList(first, first+(dataSize%pageSize));
}
} else {
return data;
}
}
我的问题:
datatable 被渲染,并按照预期的方式显示数据。
现在我想根据一个(或多个)列对 table 进行排序。加载方法被调用,但是移交给我的加载方法的 sortfield-string 是错误的(确切地说:"property]" 被打印)。
据我了解我的语法应该没有错,正如我所说的数据显示是完全正确的。 (所以语法适用于输出文本,但不适用于 p:column 中的 sortBy 子句?!)
我的 primefaces-components 语法有问题吗?
还有为什么只交了属性],没有交完整的String? (如果是 cTable[colC.property] 被移交,我会以某种方式理解这种情况,但由于它只是字符串的后半部分,老实说我完全无能为力。
如果能帮我解决问题,并在最好的情况下提供解决方法,那就太好了:)
好的,我已经开始工作了。
似乎 forEach 确实是麻烦的根源 here.Thanks 让我走上正轨 @perissf
最后一件很有趣的事情是为什么它只传递了表达式的一部分,但是^^
对于任何人 interested/facing 这里的类似问题是对我来说工作正常的代码:
数据表:
<p:dataTable id="cTable" var="cTable" value="#{backingbean.lazyC}" paginator="true"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="5,10,15" rows="10" sortMode="multiple" lazy="true" rendered="#{backingBean.cAvailable}">
<p:columns value="#{backingBean.headerAllocationC}" var="colC" sortBy="#{cTable[colC.property]}">
<f:facet name="header">
<h:outputText value="#{colC.header}"/>
</f:facet>
<h:outputText value="#{cTable[colC.property]}"/>
</p:columns>
</p:dataTable>
懒惰数据模型:
public class LazyCDataModel extends LazyDataModel<cBean>{
private static final long serialVersionUID = 1L;
private List<cBean> datasource;
public LazyCDataModel (List<cBean> datasource) {
this.datasource = datasource;
}
@Override
public List<cBean> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String,Object> filters){
List<cBean> data = new ArrayList<cBean>();
for (cBean c : datasource) {
boolean match = true;
if (filters != null) {
for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
try {
String filterProperty = it.next();
Object filterValue = filters.get(filterProperty);
String fieldValue = String.valueOf(bestand.getClass().getField(filterProperty).get(bestand));
if (filterValue == null || fieldValue.startsWith(filterValue.toString())) {
match = true;
}
else {
match = false;
continue;
}
} catch (Exception e) {
match = false;
}
}
}
if (match) {
data.add(c);
}
}
if (multiSortMeta != null) {
for (SortMeta sortMeta : multiSortMeta) {
if (sortMeta.getSortField() != null) {
Collections.sort(data, new LazyCSort(sortMeta.getSortField(),sortMeta.getSortOrder()));
}
}
}
int dataSize = data.size();
this.setRowCount(dataSize);
if (dataSize > pageSize) {
try {
return data.subList(first, first+pageSize);
} catch (IndexOutOfBoundsException e) {
return data.subList(first, first+(dataSize%pageSize));
}
} else {
return data;
}
}
}
最后我的 LazySorter:
public class LazyCSort implements Comparator<cBean>{
private String sortField;
private SortOrder sortOrder;
public LazyBestandsSort(String sortField, SortOrder sortOrder) {
this.sortField = sortField;
this.sortOrder = sortOrder;
}
public int compare(cBean c1, cBean c2) {
try {
Field field1 = BestandsBean.class.getDeclaredField(this.sortField);
Field field2 = BestandsBean.class.getDeclaredField(this.sortField);
field1.setAccessible(true);
field2.setAccessible(true);
Object value1 = field1.get(bestand1);
Object value2 = field2.get(bestand2);
int value = ((Comparable) value1).compareTo(value2);
return SortOrder.ASCENDING.equals(sortOrder) ? value : -1 * value;
} catch (Exception e){
e.printStackTrace();
}
}
}
注意:
在 LazySorter 中,我需要选择 "cBean.class.getDeclaredField",因为我在 cBean 中的字段是私有的。如果您有 public 个字段,您可以使用普通的 "getField",如 primefaces-Showcase
中所示
我的延迟加载数据有问题table。 首先,这里的代码:
<p:tabView>
<!-- Tabs A and B, working fine -->
<p:tab title="C">
<p:commandButton value="get C" id="openC" actionListener="#{backingBean.initC}" render="cTable" update="cTable"></p:commandButton>
<p:separator/>
<p:dataTable id="cTable" var="cTable" value="#{backingBean.lazyC}" paginator="true"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="5,10,15" rows="10" sortMode="multiple" lazy="true" rendered="#{backingBean.cAvailable}">
<c:forEach var="colC" items="#{backingBean.headerAllocationC}">
<p:column headerText="#{colC.header}" sortBy="#{cTable[colC.property]}">
<div align="center">
<h:outputText value="#{cTable[colC.property]}"></h:outputText>
</div>
</p:column>
</c:forEach>
</p:dataTable>
</p:tab>
</p:tabView>
遵循我的惰性数据模型的排序方法:
@Override
public List<cBean> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String,Object> filters){
List<cBean> data = new ArrayList<cBean>();
if (multiSortMeta != null) {
for (SortMeta sortMeta : multiSortMeta) {
System.out.println("SORTFIELD:" +sortMeta.getSortField());
System.out.println("SORTORDER:" +sortMeta.getSortOrder());
//System.out.println("SORTFUNCTION:"+sortMeta.getSortFunction());
System.out.println("COLUMN:" +sortMeta.getColumn());
System.out.println("CLASS:" +sortMeta.getClass());
}
}
for (cBean c : datasource) {
boolean match = true;
if (filters != null) {
for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
try {
String filterProperty = it.next();
Object filterValue = filters.get(filterProperty);
String fieldValue = String.valueOf(c.getClass().getField(filterProperty).get(c));
if (filterValue == null || fieldValue.startsWith(filterValue.toString())) {
match = true;
}
else {
match = false;
continue;
}
} catch (Exception e) {
match = false;
}
}
}
if (match) {
data.add(c);
}
}
int dataSize = data.size();
this.setRowCount(dataSize);
if (dataSize > pageSize) {
try {
return data.subList(first, first+pageSize);
} catch (IndexOutOfBoundsException e) {
return data.subList(first, first+(dataSize%pageSize));
}
} else {
return data;
}
}
我的问题: datatable 被渲染,并按照预期的方式显示数据。 现在我想根据一个(或多个)列对 table 进行排序。加载方法被调用,但是移交给我的加载方法的 sortfield-string 是错误的(确切地说:"property]" 被打印)。
据我了解我的语法应该没有错,正如我所说的数据显示是完全正确的。 (所以语法适用于输出文本,但不适用于 p:column 中的 sortBy 子句?!)
我的 primefaces-components 语法有问题吗? 还有为什么只交了属性],没有交完整的String? (如果是 cTable[colC.property] 被移交,我会以某种方式理解这种情况,但由于它只是字符串的后半部分,老实说我完全无能为力。
如果能帮我解决问题,并在最好的情况下提供解决方法,那就太好了:)
好的,我已经开始工作了。 似乎 forEach 确实是麻烦的根源 here.Thanks 让我走上正轨 @perissf
最后一件很有趣的事情是为什么它只传递了表达式的一部分,但是^^
对于任何人 interested/facing 这里的类似问题是对我来说工作正常的代码:
数据表:
<p:dataTable id="cTable" var="cTable" value="#{backingbean.lazyC}" paginator="true"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="5,10,15" rows="10" sortMode="multiple" lazy="true" rendered="#{backingBean.cAvailable}">
<p:columns value="#{backingBean.headerAllocationC}" var="colC" sortBy="#{cTable[colC.property]}">
<f:facet name="header">
<h:outputText value="#{colC.header}"/>
</f:facet>
<h:outputText value="#{cTable[colC.property]}"/>
</p:columns>
</p:dataTable>
懒惰数据模型:
public class LazyCDataModel extends LazyDataModel<cBean>{
private static final long serialVersionUID = 1L;
private List<cBean> datasource;
public LazyCDataModel (List<cBean> datasource) {
this.datasource = datasource;
}
@Override
public List<cBean> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String,Object> filters){
List<cBean> data = new ArrayList<cBean>();
for (cBean c : datasource) {
boolean match = true;
if (filters != null) {
for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
try {
String filterProperty = it.next();
Object filterValue = filters.get(filterProperty);
String fieldValue = String.valueOf(bestand.getClass().getField(filterProperty).get(bestand));
if (filterValue == null || fieldValue.startsWith(filterValue.toString())) {
match = true;
}
else {
match = false;
continue;
}
} catch (Exception e) {
match = false;
}
}
}
if (match) {
data.add(c);
}
}
if (multiSortMeta != null) {
for (SortMeta sortMeta : multiSortMeta) {
if (sortMeta.getSortField() != null) {
Collections.sort(data, new LazyCSort(sortMeta.getSortField(),sortMeta.getSortOrder()));
}
}
}
int dataSize = data.size();
this.setRowCount(dataSize);
if (dataSize > pageSize) {
try {
return data.subList(first, first+pageSize);
} catch (IndexOutOfBoundsException e) {
return data.subList(first, first+(dataSize%pageSize));
}
} else {
return data;
}
}
}
最后我的 LazySorter:
public class LazyCSort implements Comparator<cBean>{
private String sortField;
private SortOrder sortOrder;
public LazyBestandsSort(String sortField, SortOrder sortOrder) {
this.sortField = sortField;
this.sortOrder = sortOrder;
}
public int compare(cBean c1, cBean c2) {
try {
Field field1 = BestandsBean.class.getDeclaredField(this.sortField);
Field field2 = BestandsBean.class.getDeclaredField(this.sortField);
field1.setAccessible(true);
field2.setAccessible(true);
Object value1 = field1.get(bestand1);
Object value2 = field2.get(bestand2);
int value = ((Comparable) value1).compareTo(value2);
return SortOrder.ASCENDING.equals(sortOrder) ? value : -1 * value;
} catch (Exception e){
e.printStackTrace();
}
}
}
注意: 在 LazySorter 中,我需要选择 "cBean.class.getDeclaredField",因为我在 cBean 中的字段是私有的。如果您有 public 个字段,您可以使用普通的 "getField",如 primefaces-Showcase
中所示