Olá, pessoal!
Hoje veremos como podemos resolver o LazyInitializationException em cinco minutos. Dificilmente um desenvolvedor não passou por essa exceção. Não vou entrar em detalhes sobre o motivo do LazyInitializationException, mas tenho certeza que você vão gostar da facilidade!
Na prática
Para mostrar a solução na prática, vou pegar um exemplo simples: vamos considerar o relacionamento de que um Type tem muitos Users. Veja:
@Entity @Table(name = "type") public class Type implements java.io.Serializable { private static final long serialVersionUID = 2644022136811709451L; private Long id; private String description; private Set<User> users = new HashSet<User>(); public Type() { } @Id @GeneratedValue @Column(name = "ID", unique = true, nullable = false) public Long getId() { return this.id; } @OneToMany(fetch = FetchType.LAZY, mappedBy = "type", targetEntity=User.class) public Set<User> getUsers() { return this.users; } //getters/setters omitidos } User.java @Entity @Table(name = "user", uniqueConstraints = @UniqueConstraint(columnNames = "EMAIL")) public class User implements java.io.Serializable,Comparable<User> { private static final long serialVersionUID = 9108778602728711429L; //declaração de variaveis omitidas @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "TYPE_ID",nullable=false) public Type getType() { return this.type; } //getters/setters omitidos }
Nada de especial até aqui; apenas o relacionamento que já conhecemos.
O problema
Agora que temos o problema, quando o User.java tentar acessar o Type e a conexão já estiver fechada, já sabemos que vamos resolver com LazyInitializationException. Uma forma para resolver é usando o join fetch, que evitará o problema pelo seguinte motivo:
- Apenas uma consulta será feita e evitamos o problema N + 1;
- A realização da consulta vai deixar de ser Lazy para Eager. Isso é diferente de você mudar de Lazy para Eager.
No DAO
Devemos ter a consulta assim:
public class UserDAO{ public List<User> readAll() { //avoiding LazyInitializationException join fetch String hql = "select u from User u join fetch u.type"; Query query = getCurrentSession().createQuery(hql); return query.list(); } }
Pronto! Resolvido seu problema com LazyInitializationException. Um detalhe importante é que para cada coleção que temos, é uma consulta que devemos ter. Se Type tem uma coleção de acesso, é uma consulta.
Bom, é isso. Vou ficando por aqui e espero que tenham gostado do artigo.
Abraços!