Back-End

16 mai, 2014

Resolvendo LazyInitializationException Java em 5 minutos

Publicidade

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!