Gostaria de saber porque quando faço uma busca simples no BD usando JSF ele repete pelo menos 3 vezes a mesma consulta antes de ir para o jsp que mostra o resultado.
Obrigado
Gostaria de saber porque quando faço uma busca simples no BD usando JSF ele repete pelo menos 3 vezes a mesma consulta antes de ir para o jsp que mostra o resultado.
Obrigado
Opa,
Bem geralmente ele repete o método get 2 vezes, uma antes do processamento de sua action e outra depois, seguindo o ciclo de vida do Faces. Bem sugiro que crie um atributo de instância e em um backing bean de escopo request e no método get faça a pesquisa no banco apenas se o objeto estiver nulo.
:okok:
Isso acontece porque o nome do método começa com get ou nada a ver? Pelo menos para cadastrar, editar e excluir ele passa somente uma vez pelo método e não começa com get.
Isso que sugeriu seria como um flag no inicio do método por exemplo com um valor true, e depois de ele executa uma condição se o flag for true executa o sql e depois muda o flag para false ou não?
Obrigado
Na verdade o problema é que quando você associa a um atributo na sua view que acontece isso, porque ele executa nas duas fases como disse no post anterior. E a função é executada apenas na fase de execução.
:okok:
OK, entendi o que está acontecendo, mas não entendi como resolver isso:
Poderia dar um exemplo para esclarecer melhor?
Obrigado
Uma coisa que percebi é que se eu tiver 30 itens sendo listados na tela pelo dataTable ele repete 30 vezes o método chamado pelo commandLink, isso acaba com a performance de qualquer BD, alguém saberia como posso resolver isso?
Opa,
faça o que eu já lhe falei, crie uma variavel global e faça a seleção apenas uma vez. Aí no seu método que retorna a lista, você faz os testes se a variável já tiver sido preenchida, ele apenas retorna ela, senão ele lista no banco e salva nesta variável.
Quanto o que você falou não tem muita idéia não, pode ser que você fez alguma coisa errada.
:okok:
Eu já tinha feito isso, mas quando é atualizado algum item e clico para ver os detalhes não busca novamente no BD porque a variavel global não está nula, isso resolve o problema de não repetir as buscar, mas não atualiza. Nem mesmo clicando em outro link, tenho que sair e entrar novamente para poder atualizar.
ah bom, matenha isto na e quando você atualizar alguma informação lembre-se de limparar estes dados.
:okok:
Não sei mais o que fazer… tentei de tudo, da uma olhada no meu código se estou fazendo alguma coisa errada, esta é a classe:
public String buscar() throws AlmoxarifadoExceptions {
String result = "FALHA";
try {
//para pegar valor do commandLink
FacesContext context = FacesContext.getCurrentInstance();
Map map = context.getExternalContext().getRequestParameterMap();
tipoID = Integer.parseInt((String) map.get("tipoID"));
tipoDAO.buscar(tipoID);
result = "SUCESSO";
} catch (SQLException sqlBuscarTipo) {
result = "FALHA";
throw new AlmoxarifadoExceptions(sqlBuscarTipo.getClass().getName(),
"buscarTipo", sqlBuscarTipo.getMessage());
}
return result;
}
O método buscar é esse:
public void buscar(int tipoID) throws AlmoxarifadoExceptions, SQLException {
try {
bd.open();
bd.psmt = bd.conn.prepareStatement("SELECT * FROM Tipos " +
"WHERE TipoID = ?");
bd.psmt.setInt(1, tipoID);
bd.rs = bd.psmt.executeQuery();
if (bd.rs.next()) {
preencheTipos(tipoDTO);
}
} finally {
bd.closeAll();
}
}
O preencheTipos vai setar os beans só, na página esta assim:
<t:dataTable
id="listar"
value="#{tipoSession.listar}"
var="dados"
rows="25">
<h:column>
<f:facet name="header">
<h:outputText value="#{msgs.tiposTipo}" styleClass="textoColunas"/>
</f:facet>
<h:outputText value="#{dados.tipo}" styleClass="texto"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="#{msgs.tiposInsumo}" styleClass="textoColunas"/>
</f:facet>
<h:outputText value="#{dados.insumo}" styleClass="texto"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="#{msgs.tiposDetalhes}" styleClass="textoColunas"/>
</f:facet>
<h:commandLink value="#{msgs.detalhes}" styleClass="texto" action="#{tipoSession.buscar}">
<f:param name="tipoID" value="#{dados.tipoID}"/>
</h:commandLink>
</h:column>
</t:dataTable>
Já tentei usando uma variavel global que muda de valor quando é realizado a busca apenas uma vez, já tentei limpar os dados depois de realizar a busca uma vez, o problema é que se tiver 25 dados na tela ele executa 25 vezes a mesma consulta.
Obrigado pela ajuda!
coloque para mim seu método listar… porque desta forma que você colocou não dá para saber…
:okok:
O método listar é este:
public Result getListar() throws AlmoxarifadoExceptions, SQLException {
try {
bd.open();
bd.psmt = bd.conn.prepareStatement("SELECT * FROM Tipos ORDER BY Tipo");
bd.rs = bd.psmt.executeQuery();
return ResultSupport.toResult(bd.rs);
} finally {
bd.closeAll();
}
}
O método buscar é quando clico no link para pegar o registro pelo ID, esse método buscar repete dependento do número de registros na tela, se tiver 25 registros repete 25 vezes o método, fazendo 25 vezes a mesma consulta, tem alguma coisa muito errada nisso… mas não tá fácil encontrar
Obrigado novamente
Tentei usar um binding UIData e um HtmlDataTable para pegar o valor selecionado no dataTable, tentei também
FacesContext ctx = FacesContext.getCurrentInstance();
ValueBinding binding = ctx.getApplication().createValueBinding("#{dados}");
Ambos funcionam mas ambos repetem o mesmo método conforme o número de dados mostrados na tela. Já não sei mais o que fazer…
[quote=“fpmx”]O método listar é este:
public Result getListar() throws AlmoxarifadoExceptions, SQLException {
try {
bd.open();
bd.psmt = bd.conn.prepareStatement("SELECT * FROM Tipos ORDER BY Tipo");
bd.rs = bd.psmt.executeQuery();
return ResultSupport.toResult(bd.rs);
} finally {
bd.closeAll();
}
}
O método buscar é quando clico no link para pegar o registro pelo ID, esse método buscar repete dependento do número de registros na tela, se tiver 25 registros repete 25 vezes o método, fazendo 25 vezes a mesma consulta, tem alguma coisa muito errada nisso… mas não tá fácil encontrar
Obrigado novamente[/quote]
tenta armazenar o resultado e só consultar se a variavel for nula, algo como:
private Result lista;
public Result getListar() throws AlmoxarifadoExceptions, SQLException {
if (lista!=null)
return lista;
try {
bd.open();
bd.psmt = bd.conn.prepareStatement("SELECT * FROM Tipos ORDER BY Tipo");
bd.rs = bd.psmt.executeQuery();
lista = ResultSupport.toResult(bd.rs);
return lista;
} finally {
bd.closeAll();
}
}
[quote=“fpmx”]Tentei usar um binding UIData e um HtmlDataTable para pegar o valor selecionado no dataTable, tentei também
FacesContext ctx = FacesContext.getCurrentInstance();
ValueBinding binding = ctx.getApplication().createValueBinding("#{dados}");
Ambos funcionam mas ambos repetem o mesmo método conforme o número de dados mostrados na tela. Já não sei mais o que fazer…[/quote]
a forma mais fácil de saber a linha selecionada em um datatable é usando um table listener para o datamodel.
seta os dados da tabela para um ListDataModel (que pode ser criado a partir de uma List)
e adiciona um DataModelListener neste cara e pronto
ou então coloca um t:updateActionListener na tua tabela (componente do tomahawk)
ou se estiver usando o spring-annotation:
@DataModel e @DataModelSelection ja resolvem …
Isso de armazenar o resultado é o que estou usando por enquanto, mas tem um problema, se outra pessoa atualizar algum dado de um registro para mim aparece desatualizado porque a variavel não está vazia.
Usando o t:updateActionListener para pegar o ID não está funcionando ele repete o método chamado pelo commandLink conforme o número de registros mostrados pelo dataTable e mostra na tela de edição somente o último registro.
Estou pesquisando sobre o ListDataModel, mas se alguém tiver um exemplo facilita…
O que eu acho estranho é que ele deveria ir para a tela de edição já na primeira passada, pois o método retorna a String para mostrar a outra tela já na primeira passada pelo método, não consigo entender porque isso não acontece.
para resolver isto muda o scope do bean para request …
um singleton não deveria ser o backing bean de uma página (pelo menos não em uma situacão normal :S )
Mudando o scope para request apresentou essa mensagem: java.lang.NullPointerException
Não tá fácil pegar esse registro do dataTable sem repetir o método, já tentei de tudo consigo pega o valor de pelo menos umas 5 formas diferentes, porém todas elas repetem o método buscar conforme quantos registros o dataTable mostra, será que o problema não está no dataTable?
Opa,
mais fácil é você passar o identificador do registro como parâmentro do seu command link… muito mais simples.
use o f:param para isto. quanto ao nullpointerexception tome cuidade que você está tentando fazer alguma referência ao seu objeto enquanto ele ainda está vazio/nulo.
:okok:
Usando o f:param como estava usando desde o começo consigo pegar o ID do item que quero alterar, mudei o scope para Request e funcionau normalmente assim como scope Session também, porém o problema de repetir o método 10 vezes se tiver 10 registros mostrados pelo dataTable ainda continua.
O erro java.lang.NullPointerException estava dando quando tentava pegar o parametro com o scope Request através do t:updateActionListener.
Usando o DataModel teoricamente o método não se repetiria, ou será que está repetindo porque meu dataTable ou o commandLink esta implementando errado? Como faço para usar esse DataModel, já testei alguns exemplos que achei no google, mas mesmo assim o método chamado pelo commandLink insiste em repetir…