Обновление объекта бина на RowEdit
Я создаю страницу CRS JSF 2.2, используя простые данные, которые можно датировать вместе с RowEditor.
Моя проблема заключается в редактировании строки. Я использую 2 разных слушателя для сравнения записи до и после редактирования (чтобы убедиться, что есть какие-либо изменения и т. Д.)
Для этого я использую RowEditInit, чтобы получить начальное значение, как только пользователь нажимает на значок карандаша.
После того, как пользователь изменяет данные строки, я использую событие RowEdit, чтобы выполнить некоторые проверки и сравнить значения до и после, но мой исходный объект в итоге получает те же значения, которые пользователь ввел после нажатия кнопки "Сохранить".
HTML-код
<h:form id="edicao" prependId="false">
<p:growl id="msgs" showDetail="true" globalOnly="true" escape="true"/>
<p:dataTable id="dataTable" var="linha" value="#{perfilMB.listaPerfilEntities}"
editable="true" draggableColumns="true" rendered="#{not empty perfilMB.listaPerfilEntities}"
widgetVar="tablePerfil" filteredValue="#{perfilMB.filteredPerfilEntities}"
emptyMessage="Não existem registros." resizableColumns="true" styleClass="datatable_cadastro" >
<f:facet name="header">
<span class="titulo_datatable" >Tabela Perfil</span>
<p:commandButton id="toggler" type="button" value="Colunas" />
<p:columnToggler datasource="dataTable" trigger="toggler" />
</f:facet>
<p:ajax event="rowEdit" listener="#{perfilMB.onRowEdit}" update=":edicao:msgs" />
<p:ajax event="rowEditCancel" listener="#{perfilMB.onRowCancel}" update=":edicao:msgs" />
<p:ajax event="rowEditInit" listener="#{perfilMB.rowEditInit}" />
<p:column headerText="ID" sortBy="#{linha.id}"
style="width:50px;">
<p:outputLabel value="#{linha.id}" style="width:100%" />
</p:column>
<p:column headerText="NOME" filterBy="#{linha.perfil}"
filterMatchMode="contains" sortBy="#{linha.perfil}"
style="width:100%;">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{linha.perfil}" />
</f:facet>
<f:facet name="input">
<p:inputTextarea value="#{linha.perfil}" id="nome"
update=":edicao" style="width:100%" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="DETALHAMENTO"
style="width:100%;"
sortBy="#{linha.descritivo}" filterBy="#{linha.descritivo}"
filterMatchMode="contains">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{linha.descritivo}" />
</f:facet>
<f:facet name="input">
<p:inputTextarea value="#{linha.descritivo}"
id="detalhamento" update=":edicao" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="ATIVO" style="width:150px;" filterBy="#{linha.ativo}" filterMatchMode="equals">
<f:facet name="filter">
<p:selectOneMenu onchange="PF('tablePerfil').filter()" >
<f:converter converterId="javax.faces.Character"/>
<f:selectItem itemLabel="TODOS" itemValue=""/>
<f:selectItem itemLabel="ATIVO" itemValue="T"/>
<f:selectItem itemLabel="INATIVO" itemValue="F"/>
</p:selectOneMenu>
</f:facet>
<p:cellEditor>
<f:facet name="output">
<p:selectBooleanCheckbox value="#{perfilMB.charToBool(linha.ativo)}" disabled="true"/>
</f:facet>
<f:facet name="input">
<p:selectBooleanCheckbox value="#{perfilMB.ativo}" id="ativo" immediate="true" update=":edicao" style="width:100%"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="!" style="width:40px">
<p:rowEditor />
</p:column>
<p:column headerText="X" style="width:40px">
<p:commandLink styleClass="ui-icon ui-icon-trash" action="#{perfilMB.preparaParaDeletar(linha)}" update=":confirmacao_exclusao" oncomplete="PF('confirmacao').show()" />
</p:column>
</p:dataTable>
</h:form>
BEAN
@ViewScoped
импорт
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import org.primefaces.event.RowEditEvent;
Процедура:
1 - пользователь нажимает кнопку "Редактировать строку", вызывая RowEditInit.
2 - Объект perfilAntes получает начальное значение из этой строки.
Метод RowEditInit
public void rowEditInit(RowEditEvent event) {
Object value = event.getObject();
perfilAntes = new PerfilEntity();
perfilAntes = (PerfilEntity) value;
}
3 - После того, как пользователь заканчивает редактирование данных, он нажимает кнопку "Сохранить", которая вызывает метод RowEdit.
4 - новые имена объектов perfilTela получает новое значение, введенное пользователем.
5 - Вызвать метод validaOnRowEdit, который сравнивает два объекта друг с другом.
Метод RowEdit
public void onRowEdit(RowEditEvent event) {
context = FacesContext.getCurrentInstance();
Object value = event.getObject();
PerfilEntity perfilTela = (PerfilEntity) value;
if(perfilTela.getId() != null){
/* Calls the validation method */
boolean validado = validaOnRowEdit(perfilTela);
/* if its all Good, saves the data on database*/
if(validado){
/*removed code*/
}
}
Метод проверки данных
Этот метод сравнивает два объекта: PerfilAntes (начальное значение) с PerfilTela (значение, введенное пользователем).
Когда я проверяю значения объекта, объект PerfilAntes теряет свое начальное значение и он равен объекту PerfilTela!
public boolean validaOnRowEdit(PerfilEntity perfilTela){
if(perfilAntes.getId() != null){
if( perfilTela.getPerfil().trim() != null && perfilTela.getDescritivo().trim() != null ){
if( perfilTela.getPerfil().equals(perfilAntes.getPerfil() )
&& perfilTela.getDescritivo().equals(perfilAntes.getDescritivo() )
&& perfilTela.getAtivo() == perfilAntes.getAtivo() ){
perfilTela = perfilAntes;
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Changes Canceled" ,"There was no changes in row <br/><b>Case Insensitive<b/>" ));
return false;
} else {
return true;
}
} else {
perfilTela = perfilAntes;
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Changes canceled" ,"No field can be empty or contain spaces" ));
return false;
}
}
}
2 ответа
Я выяснил, в чем проблема.
При использовании переменных объекта вы создаете объекты и устанавливаете значения следующим образом:
Object object1 = new Object();
Object object2 = new Object();
object1 = object2;
Переменные объектов не сохраняют значения объектов внутри этих переменных, вместо этого они сохраняют только ссылку между переменной в памяти стека и кучи.
Поэтому, когда я установил: object1 = object2;
Объект1 получает "указатель" на объект, установленный на объекте2, и если я отредактирую один из атрибутов, используя любую из этих переменных, оба будут изменены, поскольку он содержит только ссылку.
И поскольку я установил object1 = object2, ранее связанный объект на object1, который существует в куче, больше не может использоваться и будет очищен сборщиком мусора.
Так что я закончил настройку значений с помощью сеттеров.
Попробуйте использовать компонент @SessionScoped и посмотрите, что получится, ваш код выглядит нормально.