4
respostas

query funciona mesmo com entity manager fechado?

Boa noite, estou com a seguinte duvida...

Executei este codigo:

public static void main(String[] args) {

        EntityManager em = new JPAUtil().getEntityManager();
        em.getTransaction().begin();

        String jpql = "Select c FROM Conta c";
        Query query = em.createQuery(jpql);
        @SuppressWarnings("unchecked")
        List<Conta> todasContas = query.getResultList();


        em.close();

        for (Conta conta : todasContas) {
            System.out.println("Titular: " + conta.getTitular());
            System.out.println("Movimentacoes: " + conta.getMovimentacoes());
        }

        System.exit(0);
    }

}

E funcionou igual a primeira forma feita no video, (Lazy)... minha duvida é a seguinte, como ele fez a query de forma lazy qdo eu chamei o .getMovimentacoes() sendo que eu ja tinha fechado o EntityManager? (em.close()) ???

depois fiz dessa outra forma:

public static void main(String[] args) {

        EntityManager em = new JPAUtil().getEntityManager();

        String jpql = "Select c FROM Conta c";
        Query query = em.createQuery(jpql);
        @SuppressWarnings("unchecked")
        List<Conta> todasContas = query.getResultList();
        for (Conta conta : todasContas) {
            System.out.println("Titular: " + conta.getTitular());
            System.out.println("Movimentacoes: " + conta.getMovimentacoes());
        }


        em.close();


        System.exit(0);
    }

Ou seja, joguei o laco do for antes do em.close e APAGUEI a linha em.getTransaction().begin()... e tbm funcionou da forma lazy, sem dar excecao...

Resumindo minhas duvidas: 1) como no primeiro codigo ele fez novas querys no banco qdo da chamada do metodo .getMovimentacoes() se o EntityManager ja estava fechado?

2) no segundo codigo, pq mesmo eu omitindo a linha em.getTransaction().begin() tudo funciona normalmente?

Obrigado.

4 respostas

Olá João,

Realmente no primeiro caso deveria ter dado uma LazyInitializationException, até fiz um exemplo bem parecido com o seu e no meu caso lançou a Exception. Posta aqui os códigos das suas entidades Conta e Movimentacao pra gente verificar se tem algo que possa estar afetando. O persistence.xml também, por favor.

Sobre o segundo caso, como estamos apenas consultando o banco, não temos necessidade de ter uma transação aberta. Ela só vai ser necessária quando você precisar realizar alguma alteração no banco como nos casos da inserção, remoção e alteração.

package br.com.caelum.financas.modelo;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class Conta {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    private String titular;
    private String numero;
    private String banco;
    private String agencia;
    @OneToMany(mappedBy="conta")
    private List<Movimentacao> movimentacoes;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitular() {
        return titular;
    }

    public void setTitular(String titular) {
        this.titular = titular;
    }

    public String getNumero() {
        return numero;
    }

    public void setNumero(String numero) {
        this.numero = numero;
    }

    public String getBanco() {
        return banco;
    }

    public void setBanco(String banco) {
        this.banco = banco;
    }

    public String getAgencia() {
        return agencia;
    }

    public void setAgencia(String agencia) {
        this.agencia = agencia;
    }

    public List<Movimentacao> getMovimentacoes() {
        return movimentacoes;
    }

}
package br.com.caelum.financas.modelo;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
public class Movimentacao {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private BigDecimal valor;
    @Enumerated(EnumType.STRING)
    private TipoMovimentacao tipo;
    @Temporal(TemporalType.TIMESTAMP)
    private Calendar data;
    private String descricao;
    @ManyToOne
    private Conta conta;
    @ManyToMany
    private List<Categoria> categorias;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public BigDecimal getValor() {
        return valor;
    }

    public void setValor(BigDecimal valor) {
        this.valor = valor;
    }

    public TipoMovimentacao getTipo() {
        return tipo;
    }

    public void setTipo(TipoMovimentacao tipo) {
        this.tipo = tipo;
    }

    public Calendar getData() {
        return data;
    }

    public void setData(Calendar data) {
        this.data = data;
    }

    public String getDescricao() {
        return descricao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }

    public Conta getConta() {
        return conta;
    }

    public void setConta(Conta conta) {
        this.conta = conta;
    }

    public List<Categoria> getCategorias() {
        return categorias;
    }

    public void setCategorias(List<Categoria> categorias) {
        this.categorias = categorias;
    }

}

Olá João,

Tudo certo com essas classes também, imaginei que podia estar configurado para EAGER.

Vamos fazer um teste, tenta executar o código abaixo. Esse código tem que gerar uma LazyInitializationException. Lembre-se de trocar o ID da conta para um ID de alguma conta existente no seu banco na linha do find:

public static void main(String[] args) {
    EntityManager em = new JPAUtil().getEntityManager();

    Conta c = em.find(Conta.class, 1);
    em.close();

    System.out.println(c.getMovimentacoes());
}

Depois posta aqui a saída do console pra gente ter uma ideia do que aconteceu.