[Resolvido]Duvida com expression language

20 respostas
leonardo.bilar

Fala galera blz?
Apesar de ter procurado em varios lugares não encontrei nada a respeito.

Possuo duas classes sendo elas Cliente e Cep;

Cliente:

public class Cliente {

	@Id @GeneratedValue
	private Long id;
	
	private String nome;
	
	@JoinColumn
	@OneToOne
	private Cep cep;
	private String pessoa;
	private String cgc;
	private String rg;
	private String fone;
	private String fax;

        //getters e setters....

Cep:

public class Cep {

	@Id
	@JoinColumn
	private String cep;
	private String endereco;
	private String bairro;
	private String cidade;
	private String uf;

        //getters e setters....

Como podem ver, o objeto Cliente possui Cep como atributo.

Como faço para mostrar na minha view o atributo endereço que esta na classe Cep usando Expression Language?
O Objeto retornado no meu método é do tipo Cliente.
Tentei dessa forma ${cliente.cep.endereco}, mas não funcionou.

Desde já obrigado.

20 Respostas

drsmachado

Não funcionou = não aparece nada ou apresenta erro?
A sintaxe está correta, a princípio.

surfzera

cara tenta extender a classe cliente em cep. e ver se pega. A principio a forma que você fez ta certa mesmo … era pra funcionar.

Andersonrms

Você implementou o método getCep() na classe Cliente?

caio.ribeiro.pereira

Ja tentou deixar o mapeamento OneToOne em modo Lazy?
Pois o que acontece é que considerando que você já possua getters and setters nessas classes, o seu problema é que apenas esta carregando o objeto Cliente e não o seu CEP, mas de qualquer forma ficaria mais fácil te ajudar se vc colocar o stack de erros gerado pelo Java

leonardo.bilar

Primeiramente muito obrigado a todos que estão tentando ajudar!

Não funcionou = não aparece nada ou apresenta erro?
A sintaxe está correta, a princípio.

Não funcionou = não aparece nada, não retornou nenhum erro.

Fazendo o extends de Cliente na classe Cep a aplicação da erro 404.

Sim a classe getCep() já estava implementada mas não rolou! :frowning:

Ja tentou deixar o mapeamento OneToOne em modo Lazy?
Pois o que acontece é que considerando que você já possua getters and setters nessas classes, o seu problema é que apenas esta carregando o objeto Cliente e não o seu CEP, mas de qualquer forma ficaria mais fácil te ajudar se vc colocar o stack de erros gerado pelo Java

Fiz o teste em modo Lazy, mas deixando dessa forma a query que o hibernate retorna traz apenas a tabela cliente, não esta gerando com join na tabela cep.
O problema é que não está gerando erros.
Aparentemente é exatamente isso que vc falou, está carregando o objeto Cliente, mas não o Cep, só ainda não entendi o porque.

Segue os métodos utilizados para carregar o Cliente do banco.

A View chama o método visualiza passando o id do Cliente.

Controller:

public Cliente visualiza(Long id) {
		return clienteDao.carrega(id);
	}

Dao:

public Cliente carrega(Long id) {
		return (Cliente) this.session.load(Cliente.class, id);
	}

Query retornada pelo hibernate:

select
        cliente0_.id as id0_1_,
        cliente0_.cep_cep as cep11_0_1_,
        cliente0_.cgc as cgc0_1_,
        cliente0_.fax as fax0_1_,
        cliente0_.fone as fone0_1_,
        cliente0_.nome as nome0_1_,
        cliente0_.pessoa as pessoa0_1_,
        cliente0_.rg as rg0_1_,
        cep1_.cep as cep1_0_,
        cep1_.bairro as bairro1_0_,
        cep1_.cidade as cidade1_0_,
        cep1_.endereco as endereco1_0_,
        cep1_.uf as uf1_0_ 
    from
        Cliente cliente0_ 
    left outer join
        Cep cep1_ 
            on cliente0_.cep_cep=cep1_.cep 
    where
        cliente0_.id=?

Valeuu!!!

caio.ribeiro.pereira

Quando se usa o EL ${cliente.cep.endereco} ele utiliza os getters e setters como query, e não o seu método carrega() que esta correto. O seu problema esta no mapeamento que deveria ser anotado de uma maneira que retorne direto pelos getters, entendeu?

Eu não lembro bem pois faz tempo que não trabalho com hibernate, mas irei pesquisar pelos projetos que já trabalhei, sobre essa solução…

leonardo.bilar

Valeu… entendi sua explicação

Vi que tem uns esquemas pra mapear direto nos getters, vou ver se encontro isso aqui, se conseguir posto pra vcs!

Valeu Caio.

caio.ribeiro.pereira

Ahh lembrei, no seu caso você precisa de um carregamento Lazy sim, então apenas remova o @JoinCollunm de ambas as classes, pois ele não permite carregar via Getters e Setters e na anotação da classe Cliente deixe assim: @OneToOne(fetch=FetchType.LAZY).

Por questões de performance não é recomendado usar Lazy, então tente apenas @OneToOne primeiro e se não funcionar utilize FetchType.LAZY, o importante é você remover o @JoinCollunm de ambos.

leonardo.bilar

Tentei desse jeito, mas não rolou também.
Tanto deixando só com @OneToOne e como @OneToOne(fetch=FetchType.LAZY)

A unica coisa que achei estranho quando coloca como LAZY é a query gerada pelo hibernate. É isso mesmo?

select cliente0_.id as id0_0_, cliente0_.cep_cep as cep11_0_0_, cliente0_.cgc as cgc0_0_, cliente0_.email as email0_0_, cliente0_.fax as fax0_0_, cliente0_.fone as fone0_0_, cliente0_.grupo as grupo0_0_, cliente0_.nome as nome0_0_, cliente0_.pessoa as pessoa0_0_, cliente0_.replegal as replegal0_0_, cliente0_.rg as rg0_0_ from Cliente cliente0_ where cliente0_.id=?

caio.ribeiro.pereira

Esta correto, porém é estranho não funcionar também, pois se pudesse verificar a query gerada pelo getCEP() vc veria o hibernate fazer outra query tipo inner join eu acho.

Hebert_Coelho

O default de @OneToOne é eager. Se você está querendo exibí-lo, por que colocá-lo como Lazy?

Faça o seguinte teste no método que carrega o cliente para exibir na página (mas arranca o LAZY fora):

public Cliente visualiza(Long id) { Cliente cliente = clienteDao.carrega(id); System.out.println(cliente.getCep().getEndereco()); return cliente; } Qual o resultado o que é exibido no console? (Imagino que seja esse o método que carrega na página né?)

Talvez esse post possa te ajudar:@OneToOne Unidirecional e Bidirecional

B

Na classe Cliente tente colocar

@OneToOne(targetEntity= Cep.class, cascade = {CascadeType.All})
@JoinColumn(name=“endercoCep”, referencedColumnName=“endereco”)

Tente retornar assim:
${cliente.enderecoCep}

Hebert_Coelho

bruno.jpw:

Na classe Cliente tente colocar

@OneToOne(targetEntity= Cep.class, cascade = {CascadeType.All})
@JoinColumn(name=“endercoCep”, referencedColumnName=“endereco”)

Tente retornar assim:
${cliente.enderecoCep}


Mas para acessar por cliente.enderecoCep ele terá que ter um getEnderecoCep.

caio.ribeiro.pereira

Um coisa eu tenho certeza se usar o @JoinCollumn não será carregado o objeto CEP porque perde a referência do id do banco, o certo seria apenas @OneToOne sem mais nada entre ambas as classes.

Mas como JakeFrog falou, teste o retorno do cliente.getCep().getEndereco() via java para ver o erro ou o que retorna do banco.

caio.ribeiro.pereira

Outra coisa também que esqueci de falar, mude o método carrega, que utiliza o session.load() por session.get(), talvez isso ajude também

leonardo.bilar

É esse o metodo que carrega a página sim.

Fiz o que o jakefrog falou e da esse erro:

Mar 11, 2012 2:49:04 PM org.apache.catalina.core.StandardWrapperValve invoke Grave: Servlet.service() for servlet default threw exception br.com.caelum.vraptor.InterceptionException: exception raised, check root cause for details: java.lang.NullPointerException at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:96) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:61) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:87) at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:59) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:61) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.util.hibernate.HibernateTransactionInterceptor.intercept(HibernateTransactionInterceptor.java:48) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:48) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:71) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:83) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.core.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:44) at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92) at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:58) at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Unknown Source) Caused by: java.lang.NullPointerException at br.com.adv.controller.ClienteController.visualiza(ClienteController.java:54) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:61) ... 40 more

Não deixei como Lazy, se deixar como Lazy também da erro.

Tentei da forma como bruno.jpw sujeriu mas nao deu certo, simplesmente não exibe o endereço na view, não gerando erros.
Para acontecer isso tive que criar o método getEnderecoCep.

Valeww!!!

leonardo.bilar

Ahh usei o session.get(Cliente.class, id) no método carrega, mas continua da mesma forma.

Não aparece o endereço na view.

caio.ribeiro.pereira

Cara vc praticamente fez tudo e não deu certo hein!! O NullpointerException é por falta de dados mesmo, sendo que o OneToOne deveria resolver isso via getters…

Cara duas simples perguntas, no seu registro Cliente <–> CEP é obrigatório o usuário informar ambos? Ou pode ter casos de Cliente sem CEP?
Se sim então vc terá q tratar valores nulos dentro dos métodos getCep() e getEndereço()…tipo if(this.cep == null) ou outra regra sua, pois senao vai dar Nullpointer no futuro mesmo com a modelagem correta.

E a pergunta mais pertubante, tem dados corretos no banco? tipo Cliente com CEP, isso é depois que vc refez toda modelagem via annotations? pois há uma certa diferença entre @OneToOne e @JoinCollunm que ao remover o @JoinCollunm terá que popular denovo os dados no banco via java para ter garantia de que o fluxo de dados estão corretos.

leonardo.bilar

Caio vc encontrou o problema de tudo.

Com certeza era uma coisa que eu deveria ter verificado antes mesmo de abrir o tópico. Total falta de atenção minha. :oops:
Problema = Dados no banco não preenchidos corretamente.

Ao incluir um cliente através da aplicação, ele não estava preenchendo o campo cep da tabela Cliente, preenchendo apenas da tabela Cep.
Aí ao fazer a query pelo hibernate o campo cep da tabela cliente era NULL.

Para testar preenchi o campo Cep da tabela cliente manualmente e aí sim a EL ${cliente.cep.endereco} funcionou.

Agora preciso corrigir o problema na hora de incluir um cliente pela aplicação, para que todos os campos sejam preenchidos corretamente.
Com certeza o link que o jakefrog passou vai ajudar, dei uma lida nele, mas ainda não tive a oportunidade de fazer os testes.

Muito obrigado pela ajuda e paciência de todos.

caio.ribeiro.pereira

Ai sim hein!!
Finalmente resolvido e por mínimos detalhes!

Uma dica, é sempre escrever testes unitários pelo qual vc trabalha populando uma base de dados fake, pois assim vc iria descobri esse erro mais rápido.

Utilize o JUnit para isso é uma excelente ferramenta TDD para criar suite de testes no java.

Criado 9 de março de 2012
Ultima resposta 12 de mar. de 2012
Respostas 20
Participantes 7