Problema apos resolver o problema do LazyInitializaionException

Boa tarde, estou desenvolvendo um sistema de facturação usando o JSF hibernate tenho a entidade Venda, ItemsVenda, Factura,

Factura

@Entity
public class Factura extends GenericDomain {

    @OneToOne
    @JoinColumn(nullable = false)
    private Venda venda;
    @Column(name = "data_facturacao", nullable = false)
    @Temporal(TemporalType.DATE)
    private Date dataFacturacao;
    @Column(name = "data_validade", nullable = false)
    @Temporal(TemporalType.DATE)
    private Date dataValidade;
    @Column(nullable = true, length = 10)
    private String estado;
    @Column(name = "forma_pagamento", nullable = true, length = 20)
    private String formaPagamento;
    
    @Column(name = "data_pagamento", nullable = true)
    @Temporal(TemporalType.DATE)
    private Date dataPagamento;

ItemVenda

@Entity(name = "items_venda")
public class ItemsVenda extends GenericDomain {

    @Column(nullable = false)
    private Short quantidade;
    @Column(nullable = false, precision = 15, scale = 2,name="valor_parcial")
    private BigDecimal valorParcial;

    @ManyToOne
    @JoinColumn(nullable = false)
    private Produto produto;
    @ManyToOne
    @JoinColumn(nullable = false)
    private Venda venda;

Venda

@Entity
public class Venda extends GenericDomain {

    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date horario;
    @Column(nullable = false, precision = 15, scale = 2)
    private BigDecimal valorTotal;
    @Column(nullable = false, name = "valor_subtotal", precision = 15, scale = 2)
    private BigDecimal valorSubtotal;
    @Column(nullable = false, name = "valor_pago_iva", precision = 15, scale = 2)
    private BigDecimal valorPagoIva;
    @Column(nullable = true, name = "percentagem_desconto")
    private Short percentagemDesconto;
    @Column(nullable = true, name = "valor_extenso")
    private String valorExtenso;

    @JoinColumn(nullable = false)
    @ManyToOne
    private Cliente cliente;
    @ManyToOne
    @JoinColumn(nullable = false)
    private Funcionario funcionario;
    @ManyToOne
    @JoinColumn(name = "tipo_pagamento", nullable = false)
    private TipoPagamento tipoPagamento;

    @OneToMany(fetch = FetchType.EAGER,mappedBy = "venda" )
    private List<ItemsVenda> itemsVendas;

Conseguia listar as facturas normalmente mais apartir do momento que adicionei na entidade Venda o

@OneToMany(fetch = FetchType.EAGER,mappedBy = "venda" )
private List<ItemsVenda> itemsVendas;

para poder listar os Items de cada venda. Por tanto ao listar as facturas ele repeti algumas facturas por exemplo: se a factura de uma venda X tiver 2 Items vendidos ele repeti duas vezes a factura como ilustra o formulário

Peso ajuda estou desde ontem tentando resolver o problema nao consigo

Cara tem um pattern chamado open view session ou algo assim onde vc fecha a sessão do hibernate na view, assim ele consegue pegar tudo o que é lazy

Da uma busca por estes termos

Pesquisei esta forma, porem ainda n estou conseguindo implementar

Retorne pra view as informações prontas, senão vai ter que seguir o que chamam de open session in view conforme a dica acima, resolve e tem milhares de exemplos na internet pra você testar, só não é uma boa prática. Além disso, da maneira que você está fazendo prejudica a performance com N querys sendo executadas.

Se fosse escrever SQL nativo não teria mistério, mas como está usando Hibernate então use Criteria ou HQL definindo “fetch join” na entidades relacionadas, com isso o Hibernate vai gerar um único SQL, onde os objetos estarão todos preenchidos sem precisar ficar indo no banco na hora de processar a sua view.

Open session in view: isso mesmo!

Pesquisei acerca do open session view e criei a seguinte classe
@WebFilter(servletNames = { “Faces Servlet” })
public class HibernateSessionRequestFilter implements Filter {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    Session session = HibernateUtil.getSession();
    Transaction trx = null;

    try {
        trx = session.beginTransaction();
        request.setAttribute("session", session);

        chain.doFilter(request, response);

        trx.commit();
    } catch (Exception e) {
        if (trx != null) {
            trx.rollback();
        }
    } finally {
        session.close();
    }
}

@Override
public void destroy() {
}

@Override
public void init(FilterConfig config) throws ServletException {
}

}

mais mesmo assim continuo com o problema do LIE, peso ajuda

A classe HibernateUtil 'e esta

public class HibernateUtil {
private static SessionFactory fabricaDeSessoes = criarFabricaDeSessoes();

public static SessionFactory getFabricaDeSessoes() {
    return fabricaDeSessoes;
}

public static Session getSession() {
    // TODO Auto-generated method stub
    return fabricaDeSessoes.openSession();
}

public static Connection getConexao() {
    Session sessao = fabricaDeSessoes.openSession();

    Connection conexao = sessao.doReturningWork(new ReturningWork<Connection>() {
        @Override
        public Connection execute(Connection conn) throws SQLException {

            return conn;
        }
    });
    return conexao;
}

private static SessionFactory criarFabricaDeSessoes() {
    try {
        Configuration configuracao = new Configuration().configure();

        ServiceRegistry registro = new StandardServiceRegistryBuilder().applySettings(configuracao.getProperties())
                .build();

        SessionFactory fabrica = configuracao.buildSessionFactory(registro);

        return fabrica;
    } catch (Throwable ex) {
        System.err.println("A fábrica de sessões não pode ser criada." + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

}

Esta documentação pode ajudar https://developer.jboss.org/wiki/OpenSessionInView

e aqui tem uma discussão interessante

Por mais que eu não ache uma boa prática, a maioria consegue remediar dessa forma que você postou.

Você tem que atacar o ponto do problema, onde em algum momento você está tocando numa propriedade lazy e a session já está fechada. É problema de lógica no seu fluxo.

Como falei no outro post o ideal é passar para a view todas as informações relacionadas já prontas sem necessidade de ir no banco novamente, assim não vai ter o problema de ter que obter tardiamente uma informação com a session fechada, além de não prejudicar a performance com N querys. Deixe os lazys mapeados para as associações e use HQL ou Criteria para aplicar fetch join nessas associações de acordo com as entidades relacionadas na consulta específica. Exemplo:

Obrigado ja resolvi o problema utilizei o HQL para aplicar fetch join e deu certo

**_Query query =sessao.createQuery("select v from Venda v join fetch v.itemsVendas where v.codigo = :codigo");                                     _**

query.setParameter(“codigo”, codigo);
e mudei na entidade venda removendo o fetch = FetchType.EAGER
@OneToMany(mappedBy = “venda”,targetEntity=ItemsVenda.class )
private List itemsVendas;

Foi a primeira vez a utilizar o GUJ para ajudar-me na resolução de problemas. Do fundo do meu coração agradeço a a ti peczenyj e javaflex pela vossa disponibilidade