Chaves compostas com Hibernate

Postado em por Wolmir Cezer Garbin em Hibernate | 209 Visualizações
Última atualização em:

Este post vai mostrar como criar chaves compostas no Hibernate usando @IdClass e @Embeddable

Chaves compostas com Hibernate

Chaves compostas são utilizadas frequentemente em bancos de dados, principalmente em sistemas legados. Para facilitar para você criamos um tutorial para mostrar as maneiras que pode trabalhar com chaves compostas no hibernate.

Chave Simples com Hibernate

Uma chave simples, é quando se tem apenas um identificador na tabela, geralmente usa um valor sequencial (Sequence ou Generator) para gravar corretamente cada registro no Banco de Dados. Um exemplo é mostrado na entidade Carro:

import javax.persistence.*;

@Entity
@Table(name="USUARIO")
public class Usuario {

	@Id
	private Long id;
		
	...
}

Neste caso, tem apenas a coluna ID como identificador na tabela USUARIO e será o identificador de cada registro.

Chave composta

Quando se tem apenas um identificador único é fácil criar entidades e mapea-las para que representem o nosso banco de dados, mas quando precisamos trabalhar com identificadores compostos é um pouco diferente este mapeamento. Vamos considerar que um usuário deve pertencer a uma empresa e que seus campos chaves agora serão um identificador (campo id) e a empresa (atributo empresa) representada pela entidade Usuario.

Dessa forma temos a seguinte situação:

import javax.persistence.*;

@Entity
@Table(name="USUARIO")
public class Usuario {

	@Id
	private Long id;
		
	@Id
	private Long empresa;
		
	// [...]
}

Parece tudo certo? Parece mas isso não vai funcionar ainda! Dito isso vamos as opções que o Hibernate nos fornece para trabalhar com essas chaves compostas:

Chave composta com @IdClass

A nossa primeira opção é trabalhar com @IdClass, esta opção permite escrever um código exatamente igual ao mostrado acima com o acrescimo da anotação @IdClass() passando uma classe que trata o identificador por paramentro, exemplo:

// [...]
@IdClass(UsuarioId.class)
public class Usuario {
// [...]

Veja o exemplo completo sendo mostrado as duas classes utilizadas por está opção:

Usuario.java

import javax.persistence.*;

@Entity
@Table(name="USUARIO")
@IdClass(UsuarioId.class)
public class Usuario {

	@Id
	private Long id;
		
	@Id
	private Long empresa;
		
	// [...]
}

E na classe UsuarioId.java, que vai representar a chave composta fica assim:

import java.io.Serializable;
     
public class UsuarioId implements Serializable {
	private Long id;
	private Long empresa;
     
	// must have a default construcot
	public UsuarioId() { }
     
	public UsuarioId(Long id, Long empresa) {
		this.id = id;
		this.empresa = empresa;
	}
     
	// getter e setter + equal e hasCode
}

Note que, todos os campos anotados com @Id na classe Usuario devem estar presentes na classe UsuarioId. Note ainda que é possível também utilizar @GeneratedValue na chave composta neste tipo de chave composta. No exemplo acima é possível adicionar @GeneratedValue ao atributo id.

Por último se estiver utilizando Spring Data, crie os repositórios assim:

import org.springframework.data.jpa.repository.JpaRepository;

public interface ArtData extends JpaRepository<Usuario, UsuarioId> {

}

Chave composta com @Embeddable

Esta é a outra opção para trabalhar com chaves compostas com hibernate e confesso que é a minha forma preferida. Vamos estender esta forma. Primeiro vamos criar uma classe que será nosso id, veja a classe:

import java.io.Serializable;
 
import javax.persistence.Embeddable;
 
@Embeddable
public class UsuarioId implements Serializable {
	private Long id;
	private Long empresa;
     
	// must have a default construcot
	 public UsuarioId() { }
     
	public UsuarioId(Long id, Long empresa) {
		this.id = id;
		this.empresa = empresa;
	}
     
	// getter e setter + equal e hasCode
}

A diferença entre esta classe UsuarioId para a anterior está na adição da anotação @Embeddable adicionado a classe. Visto isso podemos partir para a nossa classe Usuario.

import javax.persistence.*;
     
@Entity
@Table(name="USUARIO")
public class Usuario {
     
	@EmbeddedId
	private UsuarioId id;
				
	//[...]
}

Nesta classe note que não utilizamos @Id como no exemplo anterior, apenas @EmbeddedId informando que a classe que representa o identificador composto desta tabela é a classe UsuarioId dessa forma ficou mais simples a representação.

Por último se estiver utilizando Spring Data, crie os repositórios assim:

import org.springframework.data.jpa.repository.JpaRepository;

public interface ArtData extends JpaRepository<Usuario, UsuarioId> {

}

Conclusão sobre chaves compostas com Hibernate

De maneira simples você pode trabalhar com chaves compostas no hibernate, apenas cabe a você saber qual forma considera ser melhor para seu caso ou sua necessidade.

Não esqueça, para que suas classes sejam 100% funcionais utilize os getters e setters além do equals e hashCode, isso vai evitar problemas futuros que podem surgir, mas se quiser deixar seu código mais limpo recomendo ver este tutorial que escrevemos: Como deixar suas entidades limpas e completas

Até a próxima!

Wolmir Cezer Garbin

Wolmir Cezer Garbin


Sou formado em Desenvolvimento de Sistemas para Internet pela faculdade Mater Dei e Pós graduado em Desenvolvimento de sistemas em Java pela UTFPR. Trabalho a mais de 9 anos com desenvolvimento em Java, Android e Web utilizando as principais tecnologias do mercado. Atuo como professor na faculdade Mater Dei, programador na Garbo Software e criador do Receitas de Código.

Ver mais

Posts relacionados


Code Conference

Esta é uma conferência de código realizada na cidade de Pato Branco para dissiminar tendências e informações sobre programação e novas tecnológias

Veja mais sobre o Code Conference

Publique seu post no Receitas de Código

Agora você pode publicar seu post no Receitas de Código e compartilhar seu conhecimento com muitas pessoas!

Quero publicar