quinta-feira, 26 de fevereiro de 2015

@Embeddable e @Embedded no JPA

Sejam bem-vindos ao Preciso Estudar Sempre. Hoje iremos falar sobre duas anotações do JPA que são irmãs e não são muito conhecidas. Essas anotações são: @Embeddable e @Embedded. Antes que você me pergunte, eu te já respondo que nesse post não teremos projeto de exemplo pois, ele é de fácil entendimento. Porém, é de nível intermediário/avançado logo, eu espero que você já tenha alguns conhecimentos sobre Java e JPA.


Antes de falarmos de anotações ou annotations, é interessante perguntar: Você sabe o que é uma anotação ?

IMPORTANTE: Lembre-se de que estamos falando do universo Java. 

Uma anotação é um recurso da plataforma Java a qual, foi inserida após a versão 1.5 que, oferece o uso de metadata de forma dinâmica, sem o uso de XML, no código-fonte Java. Essas anotações são interpretadas por um compilador ou pré compilador que irá realizar alguma tarefa pré definida.

Isto é construído através de uma interface (@interface) especial no Java, em que você define os atributos que sua anotação terá. A implementação dessa interface é o uso da anotação, exemplo:

Você criou a anotação @Carro com atributos:
  • Ano
  • Modelo
  • Marca
Quando você usa a anotação @Carro e define valores para seu atributos, exemplificado abaixo, você cria uma implementação dinâmica daquela sua interface especial e pronto, a anotação está funcionando.

 @Carro(ano="2013", marca="Fiat", modelo="Uno")  
 private Carro carro;  

Como é feito para recuperar os valores passados não será abordado aqui mas sim, em um post futuro.

Agora que já sabemos o que é uma anotação, podemos entender o que são essas anotações da JPA. Para você que nunca ouvir falar sobre JPA, ela é uma das partes da plataforma JEE. A JPA representa a API de persistência do Java e possui suporte à ORM (Mapeamento Objeto-Relacional).

JPA = Java Persistence API

Você deve estar pensando agora: "Ainnnn João, com a JPA eu consigo fazer acesso e operações em banco de dados sem usar framework ?"

Sim, você consegue. Na verdade você consegue desenvolver projetos extremamente robustos só com tecnologia Java, sem frameworks. Obviamente que os frameworks nasceram para facilitar nossas vidas e não devemos ignorá-los. Porém, devemos conhecer o poderio de fogo que a nossa linguagem de programação possui.

Falar de @Embeddable e @Embedded sem falar de composição é complicado porque essas anotações trabalham com esse conceito. De uma forma resumida, composição é a técnica de compor uma classe a partir de outras classes, dessa forma você ganha diversas vantagens, como reuso, facilidade de manutenção, etc.

Exemplo:

 public class Funcionario{  
      private Long id; 
      private String nome; 
      private String email; 
      private Date dataNascimento; 
      private String matricula;     
      private Endereco endereco; 
      // gets e sets 
 } 

 public class Endereco{ 
      private Long id; 
      private String logradouro; 
      private String numero; 
      private String bairro; 
      /*outros atributos aqui*/ 
 } 

Acima temos o exemplo de que a classe Funcionario possui um atributo do tipo Endereco, ou seja, a classe Endereco compõe a classe Funcionario. Caso um dia, uma manutenção precise ser feita na classe de Endereco, todas as classes que são compostas por ela serão atualizadas automaticamente. Para refletir tal modelagem na JPA, realizamos as seguintes mudanças:
  • Marco o atributo da composição com a anotação @Embedded.
  • Marco a classe compositora com a anotação @Embeddable.
E nossa classe fica assim:

 @Entity  
 @Table(name="FUNCIONARIO")  
 public class Funcionario{  
   
      @Id  
      @Column("ID")  
      @GeneratedValue(strategy = GenerationType.AUTO)  
      private Long id;  
   
      @Column(name="NM_FUNCIONARIO")  
      private String nome;  
   
      @Column(name="EM_FUNCIONARIO")  
      private String email;  
   
      @Column(name="DT_NASCIMENTO_FUNCIONARIO")  
      private Date dataNascimento;  
   
      @Column(name="MAT_FUNCIONARIO")  
      private String matricula;  
   
      @Embedded  
      private Endereco endereco;  
   
      // gets e sets  
 }  
   
 @Embeddable  
 public class Endereco{
      @Column(name="NM_LOGRADOURO")  
      private String logradouro;

      @Column(name="NUM_LOGRADOURO")  
      private String numero;  

      @Column(name="NM_BAIRRO")  
      private String bairro;  
   
      /*outros atributos aqui*/  
 }  

Não irei explicar aqui o que significam as anotações @Entity, @Table, @Id@Column@GeneratedValue. Farei isso em um outro post.

Quando formos gravar um funcionário no nosso banco de dados, o resultado obtido será.

Figura 1 - Tabela funcionário
É possível notar que as colunas referentes à endereço estão na tabela de funcionário. Isto foi obtido pois a classe Endereco está marcada como @Embeddable e seu atributo como @Embedded. Dessa forma ela compartilha a mesma PK (Primary Key) do funcionário inserido, ou seja, tudo fica na mesma tabela. Não importa se você tem 1 ou 5 atributos embedded, todos ficaram na tabela da entidade que possui os atributos.

Viu !? Não é tão complicado assim !! Este recurso da JPA veio para ajudar os desenvolvedores. Agora você pode aplicar no seu projeto e ser feliz.

Sugestões ?! Críticas ?! Elogios ?! 

Deixe aí nos comentários ou na nossa página do facebook.

3 comentários:

Unknown disse...

Muito bom o post, tbm seria bom dizer quando não usar.

Preciso estudar sempre disse...

Olá Kelvin, primeiramente te agradeço pelo comentário. Respondendo sua pergunta, é difícil identificar um cenário exclusivo para não usar essas anotações. Cada situação possui uma solução única. Talvez, em um cenário imaginário, gravar tudo na mesma tabela não seja a melhor solução, mas em outros sejam. Não existem balas de prata em TI. Sempre comento isso aqui.

Contudo, existem algumas situações padrão em que já foi discutido o uso dessas anotações. Por exemplo, se você possui uma composição com duas entidades fortes no escopo da sua aplicação. Talvez, anotar a entidade que compõe a outra como @Embedded não seja a melhor solução pois desta forma seu software ficará mais acoplado.

Neste cenário, talvez a melhor solução seria cada entidade refletir em tabelas distintas e a entidade que é composta pela outra somente receber uma @JoinColumn.

Consegui ser claro ? Senão, deixe aí embaixo sua impressão e discutimos mais.

Abraços e você é sempre bem-vindo aqui.

Anônimo disse...

parabéns pelo conteudo, muito bem explicado por sinal. gostei também da resposta à pergunta do colega. ajudou a entender ainda mais o cenário.