我有一个primefaces的惰性数据表,如下所示:
<h:form id="form">
<p:dataTable value="#{beanReceipts.lazyModel}" paginator="true" rows="10" paginatorPosition="bottom"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="5,10,15" var="item" emptyMessage="#{bundle['NoData']}" reflow="true"
rowStyleClass="centered" styleClass="centered" lazy="true" resizableColumns="true">
<p:column style="width:24px" styleClass="centered">
<p:rowToggler/>
</p:column>
<p:column headerText="#{bundle['Name']}" filterBy="#{item.userId.name}" filterMatchMode="contains"
styleClass="centered" sortBy="#{item.userId.name}">
<h:outputText value="#{item.userId.name}"/>
</p:column>
<p:column headerText="#{bundle['Premium']}" styleClass="centered"
sortBy="#{item.userId.premiumExpiresAt}">
<p:selectBooleanCheckbox value="#{item.userId.premiumExpiresAt != null}" disabled="true"/>
</p:column>
<p:column headerText="#{bundle['Product']}" sortBy="#{item.productId}" styleClass="centered">
<h:outputText value="#{item.productId}"/>
</p:column>
<p:column headerText="#{bundle['AutoRenew']}" sortBy="#{item.autoRenew}" styleClass="centered">
<p:selectBooleanCheckbox value="#{item.autoRenew}" disabled="true"/>
</p:column>
<p:column headerText="#{bundle['ExpiresAt']}" styleClass="centered">
<h:outputText value="#{item.expiresAt}">
<f:convertDateTime type="date" pattern="dd/MM/yyyy"/>
</h:outputText>
</p:column>
<p:column headerText="#{bundle['PurchasedAt']}" sortBy="#{item.purchasedAt}" styleClass="centered">
<h:outputText value="#{item.purchasedAt}">
<f:convertDateTime type="date" pattern="dd/MM/yyyy"/>
</h:outputText>
</p:column>
<p:column headerText="#{bundle['Platform']}" sortBy="#{item.platform}" styleClass="centered">
<h:outputText value="#{item.platform}"/>
</p:column>
<p:rowExpansion>
<h:panelGrid columns="2" cellspacing="3" cellpadding="3">
<h:outputText value="#{bundle['OrderId']}" style="font-weight: bold"/>
<h:outputText value="#{item.orderId}"/>
<h:outputText value="#{bundle['PurchaseToken']}" style="font-weight: bold"/>
<h:outputText value="#{item.purchaseToken}"/>
<h:outputText value="#{bundle['IsProcessed']}" style="font-weight: bold"/>
<p:selectBooleanCheckbox value="#{item.purchasedAt != null}" disabled="true"/>
<h:outputText value="#{bundle['RawData']}" style="font-weight: bold"/>
<h:outputText value="#{item.rawData}"/>
</h:panelGrid>
<br/>
<p:commandButton actionListener="#{beanReceipts.checkPaymentForUser}" icon="ui-icon-refresh"
value="#{bundle['Validate']}"
oncomplete="window.location.reload();" onstart="PF('loadingDia').show();"
onsuccess="PF('loadingDia').hide();" style="margin: auto;display: block;"/>
</p:rowExpansion>
<p:column headerText="#{bundle['Options']}" styleClass="centered">
<p:commandButton icon="ui-icon-pencil" onsuccess="PF('editdia').show();" update=":editdia"
style="margin: 8px;">
<f:setPropertyActionListener value="#{item}" target="#{beanReceipts.editableItem}"/>
</p:commandButton>
<p:commandButton icon="ui-icon-trash" oncomplete="window.location.reload();"
action="#{beanReceipts.deleteEntity}"
onclick="if (!confirm('#{bundle['RemovePrompt']}'))return false;"
style="margin: 0 auto; text-align: center;">
<f:setPropertyActionListener value="#{item}" target="#{beanReceipts.removableItem}"/>
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
这是我的实体类:
public class UsersReceipts extends BaseEntity {
private static final long serialVersionUID = 1L;
@Basic(optional = false)
@Column(name = "RECEIPT_TYPE", nullable = false)
@Enumerated(EnumType.STRING)
private DBUserReceiptTypeEnum receiptType;
@Column(name = "AUTO_RENEW")
private Boolean autoRenew;
@Column(name = "ORDER_ID", length = 255)
private String orderId;
@Column(name = "PRODUCT_ID", length = 255)
private String productId;
@Column(name = "PACKAGE_NAME", length = 255)
private String packageName;
@Column(name = "EXPIRES_AT")
@Temporal(TemporalType.TIMESTAMP)
private Date expiresAt;
@Column(name = "PURCHASED_AT")
@Temporal(TemporalType.TIMESTAMP)
private Date purchasedAt;
@Lob
@Column(name = "PURCHASE_TOKEN", length = 65535)
private String purchaseToken;
@Basic(optional = false)
@Column(name = "PLATFORM", nullable = false, length = 8)
@Enumerated(EnumType.STRING)
private DBAppPlatformTypeEnum platform;
@Basic(optional = false)
@Lob
@Column(name = "RAW_DATA", nullable = false, length = 65535)
private String rawData;
@JoinColumn(name = "USER_ID", referencedColumnName = "ID", nullable = false)
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Users userId;
public UsersReceipts() {
}
public UsersReceipts(Integer id) {
this.id = id;
}
public UsersReceipts(Integer id, DBEntryStatusTypeEnum status, Date createdAt, DBAppPlatformTypeEnum platform,
DBUserReceiptTypeEnum receiptType, String rawData) {
this.id = id;
this.status = status;
this.createdAt = createdAt;
this.platform = platform;
this.receiptType = receiptType;
this.rawData = rawData;
}
public Boolean getAutoRenew() {
return autoRenew;
}
public void setAutoRenew(Boolean autoRenew) {
this.autoRenew = autoRenew;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public Date getExpiresAt() {
return expiresAt;
}
public void setExpiresAt(Date expiresAt) {
this.expiresAt = expiresAt;
}
public Date getPurchasedAt() {
return purchasedAt;
}
public void setPurchasedAt(Date purchasedAt) {
this.purchasedAt = purchasedAt;
}
public String getPurchaseToken() {
return purchaseToken;
}
public void setPurchaseToken(String purchaseToken) {
this.purchaseToken = purchaseToken;
}
public DBAppPlatformTypeEnum getPlatform() {
return platform;
}
public void setPlatform(DBAppPlatformTypeEnum platform) {
this.platform = platform;
}
public DBUserReceiptTypeEnum getReceiptType() {
return receiptType;
}
public void setReceiptType(DBUserReceiptTypeEnum receiptType) {
this.receiptType = receiptType;
}
public String getRawData() {
return rawData;
}
public void setRawData(String rawData) {
this.rawData = rawData;
}
@JsonIgnore
@XmlTransient
public Users getUserId() {
return userId;
}
public void setUserId(Users userId) {
this.userId = userId;
}
}
正如你已经可以看到我的每一个'收据'对象在datable有一个关系(ManyToOne)到一个'用户'对象(类)。在我的数据中,当我添加:
#{item.userId.name}
它可以显示收据所属的用户名。这也适用于
#{item.userId.premiumExpiresAt}
字段在第2列。我的问题是,当我试图排序/过滤第一和第二列在我懒惰的数据,我得到以下错误,因为关系:
SEVERE [http-nio-8080-exec-5] com.sun.faces.application.view.FaceletViewHandlingStrategy.handleRenderException Error Rendering View[/panel/receipts.xhtml]
java.lang.IllegalArgumentException: The attribute [userId.name] is not present in the managed type [EntityTypeImpl@422737256:UsersReceipts [ javaType: class entities.UsersReceipts descriptor: RelationalDescriptor(entities.UsersReceipts --> [DatabaseTable(test_esimibul.users_receipts)]), mappings: 14]].
at org.eclipse.persistence.internal.jpa.metamodel.ManagedTypeImpl.getAttribute(ManagedTypeImpl.java:148)
at org.eclipse.persistence.internal.jpa.querydef.FromImpl.get(FromImpl.java:312)
at core.AbstractFacade.getFilterCondition(AbstractFacade.java:175)
at core.AbstractFacade.count(AbstractFacade.java:131)
at core.panel.crud.LazyCrudBean$EntityLazyModel.load(LazyCrudBean.java:44)
由于exception说我需要在查询中包含usersId(在我的例子中是Users实体),所以我无法实现这一点。以下是我的AbstractFacade执行延迟加载的方法:
/**
* Returns paginated, sorted and filtered result list.
*
* @param startingAt
* @param maxPerPage
* @param sortField
* @param sortOrder
* @param filters
* @return
*/
@Override
public List<T> getAll(int startingAt, int maxPerPage, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
EntityManager em = getEntityManager();
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<T> cq = cb.createQuery(type);
Root<T> c = cq.from(type);
cq.where(getFilterCondition(cb, c, filters));
if (sortField != null) if (sortOrder == SortOrder.ASCENDING) cq.orderBy(cb.asc(c.get(sortField)));
else if (sortOrder == SortOrder.DESCENDING) cq.orderBy(cb.desc(c.get(sortField)));
List<T> results = em.createQuery(cq).setFirstResult(startingAt).setMaxResults(maxPerPage).getResultList();
em.close();
return results;
}
/**
* Returns the count of rows for the given filtering criterias.
*
* @param filters
* @return
*/
@Override
public int count(Map<String, Object> filters) {
EntityManager em = getEntityManager();
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<T> c = cq.from(type);
cq.where(getFilterCondition(cb, c, filters));
cq.select(cb.count(c));
int count = em.createQuery(cq).getSingleResult().intValue();
em.close();
return count;
}
/**
* Creates a dynamic filtering condition with the given params.
*
* @param cb
* @param c
* @param filters
* @return
*/
private Predicate getFilterCondition(CriteriaBuilder cb, Root<T> c, Map<String, Object> filters) {
Predicate filterCondition = cb.conjunction();
filters.put("status", DBEntryStatusTypeEnum.ACTIVE);
for (Map.Entry<String, Object> filter : filters.entrySet())
if (!filter.getValue().equals(""))
filterCondition = cb.and(filterCondition, cb.like(c.get(filter.getKey()), String.format("%%%s%%", filter.getValue())));
return filterCondition;
}
我需要知道在排序/过滤的惰性数据表中使用关系时如何包含它们。如果您能帮助解决这个问题,我们将不胜感激。
我不确定filterBy
是否适用于惰性数据表。我使用新的Primefaces 10 Datatable语法解决了一个类似的问题:
<p:datatable value="#{myView.lazymodel}" var="entry">
<p:column field="entry.user.name"/>
....
这样,Primeface检测关系和过滤工作正常。
我有一个p:dataTable,它存储已处理表单的结果,我执行以下操作: 填充表单值。 提交。 已填充数据表--对任何列进行筛选。 更改表单值。 提交。 使用新结果填充数据表。 对任意列排序--将显示来自#3的筛选结果。 我有一个用于筛选值的arraylist,但我没有在bean中对它做任何操作。提交时,我调用actionListener,该actionListener将dataTable强制转换
筛选数据 你可以通过 3 种方式筛选数据: 点击字段框中的向下箭头,然后选择“筛选”。 使用筛选窗格。 右击图表上的系列或数据点。 【提示】如果要清除筛选,则需要使用筛选窗格。 排序数据 你可以通过 2 种方式排序数据: 点击字段框中的向下箭头,然后选择“排序”。 使用排序窗格。
筛选数据 你可以通过 3 种方式筛选数据: 点击字段框中的向下箭头,然后选择“筛选”。 使用筛选窗格。 按住 Control 键并点按在图表的系列或数据点。 【提示】如果要清除筛选,则需要使用筛选窗格。 排序数据 你可以通过 2 种方式排序数据: 点击字段框中的向下箭头,然后选择“排序”。 使用排序窗格。
筛选数据 你可以通过 3 种方式筛选数据: 点击字段框中的向下箭头,然后选择“筛选”。 使用筛选窗格。 右击图表上的系列或数据点。 【提示】如果要清除筛选,则需要使用筛选窗格。 排序数据 你可以通过 2 种方式排序数据: 点击字段框中的向下箭头,然后选择“排序”。 使用排序窗格。
如果数据源包含许多数据或字段,你可能会发现将数据或字段限制为仅所需的内容会更为容易,从而可以简化数据选择。 筛选数据 筛选窗格让你可以方便地创建和应用为数据指定的筛选条件。在工具栏点击 “筛选”来启用筛选窗格。 若要添加一个新的条件到准则,只需简单地点击 。如果你需要在括号内添加条件,点击 。 【提示】若要在现有的条件添加括号,只需简单地右击已选择的条件并选择“使用括号分组”。若要移除括号,请右击
如果数据源包含许多数据或字段,你可能会发现将数据或字段限制为仅所需的内容会更为容易,从而可以简化数据选择。 筛选数据 若要添加一个新的条件到准则,只需简单地点击 来启用筛选窗格。 若要添加一个新的条件到准则,只需简单地点击 。如果你需要在括号内添加条件,点击 。 【提示】若要在现有的条件添加括号,只需简单地按住 Control 键并点按已选择的条件,然后选择“使用括号分组”。若要移除括号,请按住