我在MySQL數據庫中有一個表。不幸的是,在GlassFish服務器中存在JAAS認證/授權所需的組合主鍵。當存在將多個列組合爲主鍵的複合主鍵時,覆蓋/實現getRowKey()和getRowData()方法
mysql> desc group_table;
+---------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+-------+
| user_group_id | varchar(176) | NO | PRI | NULL | |
| group_id | varchar(15) | NO | PRI | NULL | |
+---------------+--------------+------+-----+---------+-------+
2 rows in set (0.05 sec)
該表格包含以下格式的數據。
mysql> select * from group_table;
+-------------------------+------------+
| user_group_id | group_id |
+-------------------------+------------+
| [email protected] | ROLE_ADMIN |
| [email protected] | ROLE_USER |
| [email protected] | ROLE_USER |
| [email protected] | ROLE_USER |
| [email protected] | ROLE_USER |
+-------------------------+------------+
5 rows in set (0.00 sec)
一個<p:dataTable>
與rowKey
工作正常,當lazy
設置爲false
。
<p:dataTable rowKey="#{row.groupTablePK.userGroupId} #{row.groupTablePK.groupId}">
...
</p:dataTable>
GroupTablePK
是@Embeddable
類(JPA)。我認爲這個課程的細節是不需要的。
當lazy
然而,能在<p:dataTable>
的getRowKey()
和getRowData()
方法需要實現。
如何做到這一點,當有一個組合主鍵需要組合的列作爲行鍵 - 唯一的行標識符?
@Named
@ViewScoped
public class UserAuthorityManagedBean extends LazyDataModel<GroupTable> implements Serializable {
private static final long serialVersionUID = 1L;
@Override
public Object getRowKey(GroupTable groupTable) {
return groupTable != null ? groupTable.getGroupTablePK() : null;
}
@Override
public GroupTable getRowData(String rowKey) {
List<GroupTable> list = (List<GroupTable>) getWrappedData();
System.out.println("rowKey : " + rowKey);
}
@Override
public List<GroupTable> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, Object> filters) {
//... setRowCount(rowCount);
//... Return a List<GroupTable> from a business Service.
}
}
上述實現不完整。
使用這些實現在<p:dataTable>
中選擇一行時,getRowData()
方法中的sout
語句顯示以下內容。
Info: rowKey : entity.GroupTablePK[ [email protected]
Info: rowKey : groupId=ROLE_USER ]
的getRowKey()
方法返回的GroupTablePK
一個實例,但getRowData()
方法只接受一個String類型參數。它不是表示組合主鍵的對象(在此爲GroupTablePK
),以便可以將其類型轉換爲適當的對象類型(GroupTablePK
),並且基於該對象可以從給定的List<GroupTable>
獲得GroupTable
的實例並獲得getRowData()
方法返回GroupTable
的實例。
如何繼續?
問題是純粹基於即刻前一個問題:
編輯:
我除了toString()
在和equals()
實現10。在GroupTablePK
中的toString()
方法返回return "entity.GroupTablePK[ userGroupId=" + userGroupId + ", groupId=" + groupId + " ]";
,但當選擇<p:dataTable>
中的行時,將調用getRowData()
方法兩次。它在兩個後續調用中以兩部分的形式返回GroupTablePK
的字符串表示形式。在第一次通話中,它返回entity.GroupTablePK[ userGroupId=aaa
,然後在第二次通話中返回groupId=ROLE_USER ]
。
它應該在一次調用中立即返回entity.GroupTablePK[ userGroupId=aaa, groupId=ROLE_USER ]
。
這種比較groupTable.getGroupTablePK().toString().equals(rowKey)
因此是不可能的,這是我在本文之前想到的。如,
@Override
public GroupTable getRowData(String rowKey) {
List<GroupTable> list = (List<GroupTable>) getWrappedData();
for (GroupTable groupTable : list) {
if (groupTable.getGroupTablePK().toString().equals(rowKey)) {
return groupTable;
}
}
return null;
}
編輯2:
以下是最短的例子去除JPA噪聲重現該問題。
試圖替代地上,
- PrimeFaces 3.5
- PrimeFaces 4.0
- PrimeFaces 5.0
- PrimeFaces 5.1
- PrimeFaces 5.2
行爲保持靜止在所有的這些PrimeFaces版本。
託管bean:
@Named
@ViewScoped
public class CompositeRowKeyManagedBean extends LazyDataModel<GroupTable> implements Serializable {
private List<GroupTable> selectedValues; // Getter & setter.
private static final long serialVersionUID = 1L;
public CompositeRowKeyManagedBean() {}
private List<GroupTable> init() {
List<GroupTable> list = new ArrayList<GroupTable>();
GroupTablePK groupTablePK = new GroupTablePK("aaa", "ROLE_ADMIN");
GroupTable groupTable = new GroupTable(groupTablePK);
list.add(groupTable);
groupTablePK = new GroupTablePK("bbb", "ROLE_USER");
groupTable = new GroupTable(groupTablePK);
list.add(groupTable);
groupTablePK = new GroupTablePK("ccc", "ROLE_USER");
groupTable = new GroupTable(groupTablePK);
list.add(groupTable);
groupTablePK = new GroupTablePK("ddd", "ROLE_USER");
groupTable = new GroupTable(groupTablePK);
list.add(groupTable);
groupTablePK = new GroupTablePK("eee", "ROLE_USER");
groupTable = new GroupTable(groupTablePK);
list.add(groupTable);
return list;
}
@Override
public List<GroupTable> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
List<GroupTable> list = init();
setRowCount(list.size());
return list;
}
@Override
public Object getRowKey(GroupTable groupTable) {
return groupTable != null ? groupTable.getGroupTablePK() : null;
}
@Override
public GroupTable getRowData(String rowKey) {
List<GroupTable> list = (List<GroupTable>) getWrappedData();
System.out.println("rowKey : " + rowKey);
for (GroupTable groupTable : list) {
if (groupTable.getGroupTablePK().toString().equals(rowKey)) {
return groupTable;
}
}
return null;
}
public void onRowEdit(RowEditEvent event) {
GroupTablePK groupTablePK = ((GroupTable) event.getObject()).getGroupTablePK();
System.out.println("grouoId : " + groupTablePK.getGroupId() + " : userGroupId : " + groupTablePK.getUserGroupId());
}
}
數據表:
<p:dataTable var="row"
value="#{compositeRowKeyManagedBean}"
lazy="true"
editable="true"
selection="#{compositeRowKeyManagedBean.selectedValues}"
rows="50">
<p:column selectionMode="multiple"></p:column>
<p:ajax event="rowEdit" listener="#{compositeRowKeyManagedBean.onRowEdit}"/>
<p:column headerText="GroupId">
<h:outputText value="#{row.groupTablePK.userGroupId}"/>
</p:column>
<p:column headerText="UserGroupId">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{row.groupTablePK.groupId}"/>
</f:facet>
<f:facet name="input">
<p:inputText value="#{row.groupTablePK.groupId}"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Edit">
<p:rowEditor/>
</p:column>
</p:dataTable>
當行試圖進行編輯,該方法onRowEdit()
被調用。如前所述,getRowData()
被調用兩次,並在後續兩次調用中產生行鍵的分割。
這是兩個領域類GroupTable
和GroupTablePK
。
public class GroupTable implements Serializable {
private static final long serialVersionUID = 1L;
protected GroupTablePK groupTablePK;
public GroupTable() {}
public GroupTable(GroupTablePK groupTablePK) {
this.groupTablePK = groupTablePK;
}
public GroupTable(String userGroupId, String groupId) {
this.groupTablePK = new GroupTablePK(userGroupId, groupId);
}
public GroupTablePK getGroupTablePK() {
return groupTablePK;
}
public void setGroupTablePK(GroupTablePK groupTablePK) {
this.groupTablePK = groupTablePK;
}
@Override
public int hashCode() {
int hash = 0;
hash += (groupTablePK != null ? groupTablePK.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
if (!(object instanceof GroupTable)) {
return false;
}
GroupTable other = (GroupTable) object;
if ((this.groupTablePK == null && other.groupTablePK != null) || (this.groupTablePK != null && !this.groupTablePK.equals(other.groupTablePK))) {
return false;
}
return true;
}
@Override
public String toString() {
return "entity.GroupTable[ groupTablePK=" + groupTablePK + " ]";
}
}
public class GroupTablePK implements Serializable {
private String userGroupId;
private String groupId;
public GroupTablePK() {}
public GroupTablePK(String userGroupId, String groupId) {
this.userGroupId = userGroupId;
this.groupId = groupId;
}
public String getUserGroupId() {
return userGroupId;
}
public void setUserGroupId(String userGroupId) {
this.userGroupId = userGroupId;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
@Override
public int hashCode() {
int hash = 0;
hash += (userGroupId != null ? userGroupId.hashCode() : 0);
hash += (groupId != null ? groupId.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
if (!(object instanceof GroupTablePK)) {
return false;
}
GroupTablePK other = (GroupTablePK) object;
if ((this.userGroupId == null && other.userGroupId != null) || (this.userGroupId != null && !this.userGroupId.equals(other.userGroupId))) {
return false;
}
if ((this.groupId == null && other.groupId != null) || (this.groupId != null && !this.groupId.equals(other.groupId))) {
return false;
}
return true;
}
@Override
public String toString() {
return "entity.GroupTablePK[ userGroupId=" + userGroupId + ", groupId=" + groupId + " ]";
}
}
哇...很好找。這是我停止使用Primefaces的原因之一,因爲這些沒有文檔的細微差別。 –
@maple_shaft:希望你喜歡這樣一個事實,即OmniFaces試圖通過拋出IllegalArgumentException來預測和覆蓋這個事實,並在開發人員將它錯誤的情況下清除所有位置的消息;) – BalusC