Acessos ao banco de dados com JSF

7 respostas
thimor

Observando o acesso ao banco de dados utilizando JSF e JPA percebi que ele faz muitos acessos seguidos ao banco de dados quando era para fazer apenas 1. Gostaria de saber se realmente é desse jeito. Para ilustrar vou exemplificar com um CRUD de Marcas.

@Entity
public class Marca implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String nome;
    @OneToMany(mappedBy = "marca")
    private List<Produto> produtos;

Agora segue o codigo do dao:

@Transactional(readOnly=true, propagation= Propagation.REQUIRED)
public class DaoGenericoImpl<T, ID extends Serializable> implements DaoGenerico<T, ID> {

    private final Class<T> oClass;
    @Autowired
    private JpaTemplate jt;

    @Override
    public List<T> listar() {
        System.out.println("chamada ao metodo listar()");
        return jt.find("select obj from " + oClass.getSimpleName() + " obj");;
    }

Agora o metodo do managedBean

@Component
@RequestScoped
@ManagedBean(name = "marcaController")
public class MarcaController {

    @Autowired
    private MarcaDao marcaDao;
    private Marca marca;
    private DataModel marcas;

    public DataModel getMarcas() {
        marcas = new ListDataModel(marcaDao.listar());
        return marcas;
    }

Agora a pagina que lista as marcas cadastradas no banco de dados.

<h:form>
            <h:dataTable value="#{marcaController.marcas}" var="marca" rendered="#{marcaController.marcas.rowCount>0}">
                <h:column>
                    <f:facet name="header">
                        CODIGO
                    </f:facet>
                    <h:outputLabel value="#{marca.id}"/>
                </h:column>
                <h:column>
                    <f:facet name="header">
                        NOME
                    </f:facet>
                    <h:outputLabel value="#{marca.nome}"/>
                </h:column>
                <h:column>
                    <f:facet name="header">
                        OPCOES
                    </f:facet>
                    <h:commandButton value="Consultar" action="#{marcaController.consultar()}"/>
                    &nbsp;
                    <h:commandButton value="Alterar" action="#{marcaController.editar()}"/>
                    &nbsp;
                    <h:commandButton value="Excluir" action="#{marcaController.excluir()}"/>
                </h:column>
            </h:dataTable>

Pelo ciclo de vida do JSF eu so chamo o metodo getMarcas() para montar a tabela 1 vez quando acesso a pagina e este por sua vez chama o metodo listar() do Dao 1 vez tambem. Acontece que quando eu rodo a aplicacao o print que coloquei no metodo aparece 10 vezes. Tanto faz o bean ser de sessao ou request. Para tirar a nêga, eu liguei o log global do mysql e la aparece o select 10 vezes tambem. Alguem sabe dizer se esse é o comportamento padrao ou um problema de configuracao?

Log do mysql:

10 Query     SET autocommit=1
                   10 Query     SET autocommit=0
                   10 Query     select marca0_.ID as ID0_, marca0_.NOME as NOME0_ from papangudb.MARCA marca0_
                   10 Query     commit
                   10 Query     SET autocommit=1
                   10 Query     SET autocommit=0
                   10 Query     select marca0_.ID as ID0_, marca0_.NOME as NOME0_ from papangudb.MARCA marca0_
                   10 Query     commit
                   10 Query     SET autocommit=1
                   10 Query     SET autocommit=0
                   10 Query     select marca0_.ID as ID0_, marca0_.NOME as NOME0_ from papangudb.MARCA marca0_
                   10 Query     commit
                   10 Query     SET autocommit=1
                   10 Query     SET autocommit=0
                   10 Query     select marca0_.ID as ID0_, marca0_.NOME as NOME0_ from papangudb.MARCA marca0_
                   10 Query     commit
                   10 Query     SET autocommit=1
                   10 Query     SET autocommit=0
                   10 Query     select marca0_.ID as ID0_, marca0_.NOME as NOME0_ from papangudb.MARCA marca0_
                   10 Query     commit
                   10 Query     SET autocommit=1
                   10 Query     SET autocommit=0
                   10 Query     select marca0_.ID as ID0_, marca0_.NOME as NOME0_ from papangudb.MARCA marca0_
                   10 Query     commit
                   10 Query     SET autocommit=1
                   10 Query     SET autocommit=0
                   10 Query     select marca0_.ID as ID0_, marca0_.NOME as NOME0_ from papangudb.MARCA marca0_
                   10 Query     commit
                   10 Query     SET autocommit=1
                   10 Query     SET autocommit=0
                   10 Query     select marca0_.ID as ID0_, marca0_.NOME as NOME0_ from papangudb.MARCA marca0_
                   10 Query     commit
                   10 Query     SET autocommit=1
                   10 Query     SET autocommit=0
                   10 Query     select marca0_.ID as ID0_, marca0_.NOME as NOME0_ from papangudb.MARCA marca0_
                   10 Query     commit
                   10 Query     SET autocommit=1

7 Respostas

Hebert_Coelho

Colocar um EAGER aqui: @OneToMany(mappedBy = “marca”).

tiago.vt

ele faz a consulta por causa do cliclo de vida do jsf a cada vez q ele faz acessa o getMarcas ele está executando a constulta, se vc fazer um if, verificando para fazer a consulta somente se o marcas for null, vc vai ver que vai cai o numero de consultas.

A

Opa, bom dia.

Acredito que ele faz isso por causa do seu …

rendered="#{marcaController.marcas.rowCount>0}"

Acredito que em todas as vezes que o JSF vai repintar a tabela ele verifica se deve exibi-la, logo, invoca seu getMarcas() que faz o select …

Acho que é isso.

[]'s

thimor

Eu fiz um projeto automatico do netbeans pelo wizard dele. E da a mesma coisa. O provedor que usei dessa vez foi o eclipselink 2.0 ao inves do hibernate. Os metodos que o netbeans criou eh parecido com as dicas que foram dadas.

//Codigo do managedbean criado pelo netbeans para retornar as marcas.
    public DataModel getItems() {
        System.out.println("chamada do metodo getItems()");
        if (items == null) {
            items = getPagination().createPageDataModel();
        }
        return items;
    }

Agora a criacao da datatable criada pelo netbans sem o rendered, porem o rendered esta no panelGroup. A quantidade de acessos é a mesma.

<h:panelGroup rendered="#{marcaController.items.rowCount > 0}">
<h:dataTable value="#{marcaController.items}" var="item" border="0" cellpadding="2" cellspacing="0" rowClasses="jsfcrud_odd_row,jsfcrud_even_row" rules="all" style="border:solid 1px">
    <h:column>
        <f:facet name="header">
                <h:outputText value="#{bundle.ListMarcaTitle_id}"/>
        </f:facet>
        <h:outputText value="#{item.id}"/>
    </h:column>
Hebert_Coelho

Ele faz o monte de consulta pq seu relacionamento é @OneToMany. Esse relacionamento é, por padrão, LAZY.

Por isso eu disse para você alterar a opção para EAGER e ver se funciona.

thimor

jakefrog:
Ele faz o monte de consulta pq seu relacionamento é @OneToMany. Esse relacionamento é, por padrão, LAZY.

Por isso eu disse para você alterar a opção para EAGER e ver se funciona.

Nesse novo projeto usando o wizard do netbeans é uma tabela so com ID e Nome, sem relacionamentos.

thimor

alex.brito:
Opa, bom dia.

Acredito que ele faz isso por causa do seu …

rendered="#{marcaController.marcas.rowCount>0}"

Acredito que em todas as vezes que o JSF vai repintar a tabela ele verifica se deve exibi-la, logo, invoca seu getMarcas() que faz o select …

Acho que é isso.

[]'s

tem 5 marcas no banco de dados. e ele da 10 selects seguidos no banco de dados. E o rendered é na tag

quando é traduzida. e o que repete ao pintar a tabela é o . Mas com o rendered fora da table o comportamento é o mesmo.
Criado 25 de novembro de 2011
Ultima resposta 25 de nov. de 2011
Respostas 7
Participantes 4