[JSF - Query - dataTable]

Amigos,

Seguinte como resolver este problema ?
Tenho uma jsp (JSF) com uma dataTable da seguinte forma:

                <h:dataTable value='#{lancamento.lancamentosProvisionado}' rendered="#{lancamento.lancamentosProvisionado != null}" var='item' border="1" cellpadding="2" cellspacing="0" style="font-size:8pt;">
                    <h:column>
                        <f:facet name="header">
                            <h:outputText value="Id"/>
                        </f:facet>                                                
                        <h:outputText value="#{item.idTitulo.id}"/>
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            <h:outputText value="Credor"/>
                        </f:facet>                                                
                        <h:outputText value="#{item.idTitulo.idCredor.nome}"/>
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            <h:outputText value="Descricao"/>
                        </f:facet>                                                
                        <h:outputText value="#{item.idTitulo.descricao}"/>
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            <h:outputText value="Valor"/>
                        </f:facet>                        
                        R$&nbsp;                        
                        <h:outputText value="#{item.valor}" >
                            <f:convertNumber pattern="###,##0.00"/>
                        </h:outputText>
                    </h:column>
                </h:dataTable>

Segue abaixo os respectivos EntityBeans:

public class Titulo implements Serializable {
    
    @Id
    @Column(name = "id", nullable = false)
    private Integer id;
    
    @Column(name = "descricao", nullable = false)
    private String descricao;
    
    @Column(name = "isMensal", nullable = false)
    private boolean isMensal;
    
    @JoinColumn(name = "idCredor", referencedColumnName = "id")
    @ManyToOne
    private Credor idCredor;
    
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "idTitulo")
    private Collection<Agendamento> agendamentoCollection;
public class Credor implements Serializable {
    
    @Id
    @Column(name = "id", nullable = false)
    private Integer id;
    
    @Column(name = "nome", nullable = false)
    private String nome;
    
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "idCredor")
    private Collection<Titulo> tituloCollection;
public class Agendamento implements Serializable {
    
    @Id
    @Column(name = "id", nullable = false)
    private Integer id;
    
    @Column(name = "numero", nullable = false)
    private int numero;
    
    @Column(name = "valor", nullable = false)
    private double valor;
    
    @Column(name = "vencimento", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date vencimento;
    
    @Column(name = "status", nullable = false)
    private boolean status;
    
    @JoinColumn(name = "idTitulo", referencedColumnName = "id")
    @ManyToOne
    private Titulo idTitulo;
    
    @JoinColumn(name = "idConta", referencedColumnName = "id")
    @ManyToOne
    private Conta idConta;
    
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "idAgendamento")
    private Collection<Lancamento> lancamentoCollection;

O problema é na query, quer dizer nao que a query esteja errada, mais como eu consigo recuperar o resuldado da query… ou como eu crio o objecto para recuperar na JSP ?

            String query = "SELECT a.idTitulo.id, c.nome, t.descricao, avg(a.valor) FROM Agendamento a, Titulo t, Credor c where a.idTitulo.isMensal = 1 and a.idTitulo.id = t.id and t.idCredor = c.id GROUP BY a.idTitulo.id, c.nome, t.descricao";
            Query q = em.createQuery(query);

como eu nao achei uma forma correcta de fazer isso eu fiz a criacao dos objectos na mao msmo.
Existe alguma forma correcta ???

Abaixo segue a forma que eu encontrei para popular o resultado da query na pagina (pagina acima)

    public DataModel getLancamentosProvisionado() {
        EntityManager em = getEntityManager();
        try{
            String query = "SELECT a.idTitulo.id, c.nome, t.descricao, avg(a.valor) FROM Agendamento a, Titulo t, Credor c where a.idTitulo.isMensal = 1 and a.idTitulo.id = t.id and t.idCredor = c.id GROUP BY a.idTitulo.id, c.nome, t.descricao";
            Query q = em.createQuery(query);
            List list = q.getResultList();
            List result = new ArrayList();
            for (int i = 0; i < list.size(); i++) {
                Object[] obj = (Object[]) list.get(i);
                Agendamento a = new Agendamento();
                Titulo t = new Titulo();
                Credor c = new Credor();
                t.setId(Integer.parseInt(obj[0].toString()));
                c.setNome(obj[1].toString());
                t.setDescricao(obj[2].toString());
                a.setValor(Double.parseDouble(obj[3].toString()));
                a.setIdTitulo(t);
                t.setIdCredor(c);
                result.add(a);
            }
            model = new ListDataModel(result);
        } finally {
            em.close();
        }
        return model;
    }

Alguem ?

Ninguem entendeu a pergunta ou ninguem sabe responder?

att,

Amigo, quando você possui diferentes tipos de objetos em cada linha essa é a maneira de se fazer.

cara, o atributo value do teu dataTable tem que referenciar alguma coisa que retorne um List do teu backing bean

não mistura JSF com Swing, porque são coisas completamente diferentes rsrs

[quote=Leozin]cara, o atributo value do teu dataTable tem que referenciar alguma coisa que retorne um List do teu backing bean

não mistura JSF com Swing, porque são coisas completamente diferentes rsrs[/quote]

lol?! :lol:

falei merda, dataModel também existe no JSF :slight_smile:

mas whatever, não use: não existe, na minha opinião, nenhuma situação plausível para utilizar o mesmo

caramba mano, e outra coisa, por que tu não faz um select mais “comum” e em JPQL pra que venha os objetos populados certinho?

assim fica difícil, mas vou te dar uma dica:

public List getLancamentosProvisionado() { Query q = em.createNamedQuery("Agendamento.listarTodos"); return q.resultList(); }

no teu dataTable ficaria assim:

<h:dataTable value="#{meuBean.lancamentosProvisionado}" var="agendamento"> <h:column> <f:facet name="header> <h:outputText value="ID" /> </f:facet> <h:outputText value="#{agendamento.id}" /> </h:column> </h:dataTable>

E assim por diante

ficou mais claro?

Cara,

Adoraria criar um SELECT simples…
Porem como vc pode observar este SELECT tem somatorias, tem calculos de médias.

String query = "SELECT a.idTitulo.id, c.nome, t.descricao, avg(a.valor) FROM Agendamento a, Titulo t, Credor c where a.idTitulo.isMensal = 1 and a.idTitulo.id = t.id and t.idCredor = c.id GROUP BY a.idTitulo.id, c.nome, t.descricao";

Quando voces tem um SELECT com campos que nao estao mapeados ou seja nao é um atributo do EntityBean como é o caso de colunas retornadas pela query que sao somas, medias, etc…, como vc’s fazem para popular isso na ???

Como eu escrevi acima, eu fiz tudo na mao, ou seja tive que criar os objetos na mao, pois nao consegui fazer com que a query criasse os objetos corretamente.

Grato.

viajei, mal não tinha entendido direito, acabei olhando rápido e até pensei que era sql nativo rsrs

mas vou dar algumas sugestões

uma delas é sempre que possível usar @NamedQueries, porque as mesmas são precisam ser recompiladas. Toda vez que você faz isso que tu fez agora, a tua query vai ser compilada e validade, que já leva um tempinho. Outra vantagem de usar namedquery é que ela é verificada se está correta logo quando sobe a aplicação, ou seja, se você está depurando a tua aplicação, não vai precisar fazer um monte de passos no teu sistema até onde a query “na mão” é feita. Você pode optar por usar Criteria do Hibernate, mas somente em casos assim, daqueles selects que variam muito hehe

Outra coisa, acho que isso pode ajudar, olha só, não vou alterar bem pouca coisa da tua query mas tu vai entender

o que eu sugiro a você é criar um DTO

olha só como é legal, tentei deixar mais ou menos parecido com o que tu quer, qualquer coisa tu adapta daí

[code]
package br.com.guj.dto
public class MeuDTO {
private Integer id;
private String nome;
private String descricao;
private BigDecimal valor;

public MeuDTO() {

}
//precisa desse tipo de construtor
public MeuDTO( Integer id, String nome, String descricao, BigDecimal valor ) {
this.id = id;
// blablabla continue o raciocinio
}

// getters/setters e construtores
}[/code]

agora a tua query ficaria mais ou menos assim:

String query = "SELECT NEW br.com.guj.dto.MeuDTO( a.idTitulo.id, c.nome, t.descricao, avg(a.valor)) FROM Agendamento a, Titulo t, Credor c where a.idTitulo.isMensal = 1 and a.idTitulo.id = t.id and t.idCredor = c.id GROUP BY a.idTitulo.id, c.nome, t.descricao"; 

E ele vai retornar um List pra você

Então ficaria muito mais fácil de usar no dataTable, só curta como ficaria essa “modificação no teu código”

Esse método a seguir é pra substituir aquele que retorna o dataModel

public List<MeuDTO> getLancamentosProvisionado() { String query = "SELECT NEW br.com.guj.dto.MeuDTO( a.idTitulo.id, c.nome, t.descricao, avg(a.valor)) FROM Agendamento a, Titulo t, Credor c where a.idTitulo.isMensal = 1 and a.idTitulo.id = t.id and t.idCredor = c.id GROUP BY a.idTitulo.id, c.nome, t.descricao"; Query query = em.createQuery( query ); return query.getResultList(); }

E ae? no teu dataTable, ficaria mais sussa ainda

<h:dataTable value='#{lancamento.lancamentosProvisionado}' rendered="#{not empty lancamento.lancamentosProvisionado}" var='item' border="1" cellpadding="2" cellspacing="0" style="font-size:8pt;"> <h:column> <f:facet name="header"> <h:outputText value="Id"/> </f:facet> <h:outputText value="#{item.id}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Credor"/> </f:facet> <h:outputText value="#{item.nome}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Descricao"/> </f:facet> <h:outputText value="#{item.descricao}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Valor"/> </f: <h:outputText value="#{item.valor}" > <f:convertNumber type="currency" minFractionDigits="2" maxFractionDigits="2" currencySymbol="R$" /> </h:outputText> </h:column> </h:dataTable>

Ficou mais fácil de entender né? Até mais limpo e menor ficou rsrs

Algumas “boas práticas by Leozin” rsrsrs

  • Evite de usar “coisas java” em expressões EL, por exemplo: ==, null, != e afins. Prefira usar as próprias “verboses” do EL, por exemplo:
    • em vez de == use “eq” por exemplo: #{1 eq 1}
    • em vez de null, utilize empty, por exemplo #{empty meuBean.minhaLista}. Esse empty retorna true se a lista for vazia (size() == 0) ou se é nula/não existir
    • existe a documentação do EL que fala dessas palavras reservadas, dá uma olhada
  • Em conversões de números, por exemplo, moeda, tu pode utilizar aquele esquema que eu fiz alí em cima, pelo menos comigo tá funcionando legal :slight_smile:
  • Sempre que possível utilizer @NamedQuery (falando pela milésima vez)

Bom são algumas dicas ae, já quebrei a cara e já trabalhei triplicado por causa de cagada, espero que vocês não passem o que eu passei rsrs e sim, JSF é muito massa :slight_smile:

espero ter ajudado

Cara,

muito massa suas dicas e suas explicacoes !!! FANTASTICO ! :slight_smile:

Valeu pela ajuda, era justamente isso que eu precisava entender!

[]'s