Mostrando postagens com marcador Annotation. Mostrar todas as postagens
Mostrando postagens com marcador Annotation. Mostrar todas as postagens

terça-feira, 24 de março de 2015

Mapeamento objeto-relacional com JPA

Olá amigos do Preciso Estudar Sempre. Hoje falaremos sobre um assunto que muitas pessoas não conhecem de forma plena e só sabem utilizar copiando e colando soluções de outras pessoas. Hoje falaremos sobre mapeamento objeto-relacional com JPA. Mas, antes de tudo, vamos definir o que é o mapeamento objeto relacional.

Mapeamento objeto-relacional é técnica de desenvolvimento que possibilita utilizar a orientação à objetos em sua base de dados relacional mas, como isso funciona? Vamos supor que temos a tabela pessoa e que nesta tabela existem diversas colunas. Utilizando a ORM (Object-Relational Mapping), ou seja, o mapeamento objeto-relacional é possível criar uma classe Pessoa a qual, representará a tabela e com atributos os quais, representarão as colunas.

Esqueça a forma tradicional de se trabalhar com banco de dados. Quando se usa ORM, é somente necessário realizar alterações em nossas coleções de objetos que isto será refletido automaticamente no banco de dados e quando for necessário realizar querys, isso também não será feito da forma tradicional. Antes você manipulava tabelas, agora você manipula classes.

Neste post não abordaremos como realizar querys usando ORM, isto ficará para um próximo post. Hoje entenderemos o básico para poder evoluir depois.

Bem, vamos voltar ao assunto e eis aqui o nosso exemplo:

Figura 1 - Tabela pessoa
Figura 2 - Classe Pessoa
No exemplo acima temos a tabela pessoa e classe Pessoa, ambas mencionadas acima. Porém, não é necessário somente criar a classe e pronto, está funcionando. Faltam ainda umas coisas. O Java não entende automaticamente que tal classe reflete tal tabela. Para isto acontecer, é necessário anotar nossas classes. Se você não sabe o que é uma anotação, clique aqui e leia sobre o assunto.

As anotações que usaremos pertencem à JPA mas, o que é JPA ? Segundo à wikipedia, a JPA é:
Java Persistence API (ou simplesmente JPA) é uma API padrão da linguagem Java que descreve uma interface comum para frameworks de persistência de dados. A JPA define um meio de mapeamento objeto-relacional para objetos Java simples e comuns (POJOs), denominados beans de entidade. Diversos frameworks de mapeamento objeto/relacional como o Hibernate implementam a JPA. Também gerencia o desenvolvimento de entidades do Modelo Relacional usando a plataforma nativa Java SE e Java EE.
A explicação acima é bem clara e agora que já sabemos o que é JPA, podemos aplicar suas anotações na nossa classe Pessoa.

 @Entity  
 @Table(name="pessoa") 
 public class Pessoa implements Serializable{ 

      @Id 
      @Column(name="id", nullable=false) 
      @GeneratedValue(strategy = GenerationType.AUTO) 
      private Long id; 

      @Column(name="nome", nullable = false, length=100) 
      private String nome; 

      @Temporal(TemporalType.DATE) 
      @Column(name = "dataNasc", nullable = false) 
      private Date dataNascimento; 

      private String email; 

      @Column(name="altura", precision=2) 
      private Double altura; 

      @Column(name="peso", precision=3) 
      private Double peso; 

      @Column(name="rg", length=9, unique=true) 
      private Integer rg; 

     /*métodos gets e sets*/ 

 } 

Você deve ter notado que aplicamos várias anotações na nossa classe, vamos entender uma por uma:

@Entity -> Anotação de escopo de classe. Representa que nossa classe será uma entidade a qual, reflete uma entidade do banco de dados e assim, poderemos manipulá-las em querys e outras operações.
@Table -> Anotação de escopo de classe. Representa que nossa entidade refletirá uma tabela do banco de dados e é onde será definido mais informações sobre a tabela alvo.
  • name: Representa o nome da tabela.
@Id -> Anotação de escopo de atributo. Representa que aquele atributo refletirá a PK da nossa tabela.
@Column -> Anotação de escopo de atributo. Representa que o nosso atributo refletirá uma coluna do banco de dados.
  • name: Representa o nome da coluna.
  • nullable: Flag que representa que a coluna aceita valores nulos. Caso seja false, a coluna/atributos não aceita valores nulos, caso contrário, aceita.
  • length: Tamanho da coluna no banco de dados.
  • precision: Usado para valores de ponto flutuante. Representa a quantidade de casas decimais da coluna.
  • unique: Representa que a coluna é uma unique key
@GeneratedValue -> Anotação de escopo de atributo. O atributo que é marcado com essa anotação terá valores gerados automaticamente. Essa anotação é usada para PKs autoincrement.
  • strategy: Representa a forma que os valores serão gerados, podem ser gerador de forma automática, através de sequence, entre outras formas.
@Temporal -> Anotação de escopo de atributo. Esta anotação representa que a coluna será do tipo date.

Você deve ter notado que o atributo email não foi mapeado. Isto não está errado e foi feito de propósito. Quando sua classe é carregada e a JPA vê que um dos atributos não foi mapeado, ela procura uma coluna no banco de dados com o mesmo nome do atributo. Como é possível notar na figura 1, realmente existe uma coluna com o nome de email logo, isto não ocasionará em nenhum erro.

Porém, se você possuir em sua classe um atributo não mapeado e a JPA não encontrar nenhuma coluna que tenha o mesmo nome, isto ocasionará um erro. Atributos não mapeados que não representam colunas do banco de dados devem ser anotados com a anotação @Transient a qual, representa que um determinado atributo de uma classe serve para o transporte de dados (DTO).

Obviamente que existem milhares de anotações e eu não sei todas até porque, isso é humanamente impossível. Neste post, eu abordei as principais, as que são mais usadas nos projetos.

Deixo aí embaixo linkado um post que foi feito aqui no blog em que discutimos sobre outras anotações da JPA. Caso você queira um livro para aprender mais sobre as anotações da JPA, dê uma olhada neste post:
Roteiro de estudo para o livro EJB 3 Profisional - Java Persistence API: http://precisoestudarsempre.blogspot.com.br/2013/09/roteiro-de-estudo-para-o-livro-ejb-3.html

Para baixar o projeto pronto, clique aqui.

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

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


Referências:
Criar anotações, é possível ?: http://precisoestudarsempre.blogspot.com.br/2015/03/criar-anotacoes-e-possivel.html
@Embeddable e @Embedded no JPA: http://precisoestudarsempre.blogspot.com.br/2015/02/embeddable-e-embedded-no-jpa.html
Documentação @Column: http://docs.oracle.com/javaee/5/api/javax/persistence/Column.html
Documentação @Entity: http://docs.oracle.com/javaee/5/api/javax/persistence/Entity.html
Documentação @Table: http://docs.oracle.com/javaee/5/api/javax/persistence/Table.html
Documentação @Transient: http://docs.oracle.com/javaee/5/api/javax/persistence/Transient.html
Leia Mais ››

segunda-feira, 2 de março de 2015

Criar anotações, é possível ?

Sejam bem-vindos ao Preciso Estudar Sempre !!

Diversas vezes no desenvolvimento de um software, é comum o uso de anotações ou annotations. Mas, você sabe o que é uma annotation ? Você já criou uma alguma vez? Então, no post dessa semana falaremos sobre a criação de annotations e iremos entender como elas funcionam.

Já adianto logo, esse post é de nível intermediário. Então, eu espero que você já possua alguns conhecimentos sobre Java. Como foi citado no Preciso Estudar Sempre:@Embeddable e @Embedded no JPA, uma annotation é uma forma dinâmica de definição de metadata.

Para download do projeto pronto, clique aqui.

Antigamente os metadados eram definidos via XML mas, isso era muito trabalhoso e a oportunidade de cometer um erro era grande. Como sabemos, metadata é nada mais nada menos que, um dado sobre um dado. Mas, o que é um dado sobre um dado? Segundo a wikipedia, a definição de metadado é:
Metadados, ou Metainformação, são dados sobre outros dados. Um item de um metadado pode dizer do que se trata aquele dado, geralmente uma informação inteligível por um computador. Os metadados facilitam o entendimento dos relacionamentos e a utilidade das informações dos dados.
Como isso pode ser refletido no ambiente de desenvolvimento ? Vamos supor que exista uma classe chamada Morador.java e uma classe Carro.java. Elas fazem parte de um sistema de condomínio. Um morador possui um carro. Na classe de morador iremos definir metadados, como:
  • Data inicial de morada (quando ele começou a morar nesse condomínio)
  • Se é inquilino ou não
Na classe de carro iremos definir:
  • Numeração da documentação do carro
  • Placa do carro
IMPORTANTE: Isto é exemplo. Para esta situação, talvez a melhor abordagem(Morador e Carro) não seja annotation.

Agora que já sabemos quais metadados pertencem ao morador e ao seu carro, podemos criar nossas annotations.

CarroAnnotation.java
 package pkg;  
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;

 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.FIELD)
 public @interface CarroAnnotation {
      String numeracaoDocumentoCarro();
      String placa();
 }

MoradorAnnotation.java
 package pkg;  
 import java.lang.annotation.ElementType; 
 import java.lang.annotation.Retention; 
 import java.lang.annotation.RetentionPolicy; 
 import java.lang.annotation.Target; 

 @Target(ElementType.TYPE) 
 @Retention(RetentionPolicy.RUNTIME) 
 public @interface MoradorAnnotation { 
      String dataInicialMoradia(); 
      boolean isInquilino() default false; 
 } 

Neste momento, você deve estar se perguntando: "Ainnnn João, o que é esse @Target e esse @Retention ??????"

Para você definir uma anotação, você precisa definir como o compilador e JVM interpretarão ela e aonde ela será aplicada. Essas anotações servem para isso.

@Target = Aonde sua annotation será aplicada.
ElementType.TYPE -> será uma anotação de classe, interface ou enum;
ElementType.FIELD -> será uma anotação de atributo;
ElementType.METHOD -> será uma anotação de método;
ElementType.CONSTRUCTOR -> será uma anotação de construtor;
ElementType.ANNOTATION_TYPE -> será uma anotação de anotação;
ElementType.LOCAL_VARIABLE -> será uma anotação de variável local;
ElementType.PACKAGE -> será uma anotação de pacote;
ElementType.PARAMETER -> será uma anotação de parâmetro.

@Retention = Como a annotation será interpretada
RetentionPolicy.SOURCE -> será utilizada apenas no código fonte: é descartada pelo compilador e pela VM;
RetentionPolicy.CLASS -> será gravada na classe, mas não será utilizada pela VM;
RetentionPolicy.RUNTIME -> será gravada na classe e utilizada pela VM, assim, pode ser lida por reflexão.

Agora que já temos nossas annotations prontas, podemos aplicá-las às nossas classes.

Carro.java
 package pkg; 

 public class Carro {
      private String modelo;
      private String marca;
      private String ano;
      private String placa;

      public String getModelo() {
           return modelo;
      }

      public void setModelo(String modelo) {
           this.modelo = modelo;
      }

      public String getMarca() {
           return marca;
      }

      public void setMarca(String marca) {
           this.marca = marca;
      }

      public String getAno() {
           return ano;
      }

      public void setAno(String ano) {
           this.ano = ano;
      }

      public String getPlaca() {
           return placa;
      }

      public void setPlaca(String placa) {
           this.placa = placa;
      }
 }

Morador.java
 package pkg;  

 @MoradorAnnotation(isInquilino=true, dataInicialMoradia="01/02/1980") 
 public class Morador { 
      private String nome; 
      private String apartamento;
 
      @CarroAnnotation(numeracaoDocumentoCarro="04958JDKDM9485", placa="KDI-9930") 
      private Carro carro; 

      public String getNome() { 
           return nome; 
      } 

      public void setNome(String nome) { 
           this.nome = nome; 
      } 

      public String getApartamento() { 
           return apartamento; 
      } 

      public void setApartamento(String apartamento) { 
           this.apartamento = apartamento; 
      } 

      public Carro getCarro() { 
           return carro; 
      } 

      public void setCarro(Carro carro) { 
           this.carro = carro; 
      } 
 } 

Pronto, nosso projeto está pronto !! Já criamos as annotations, aplicamos nas nossas classes mas falta uma coisa. Como iremos recuperar os valores que aplicamos nas anotações ??

Podemos recuperar os valores através de reflexão. Porém, isto só é possível pois configuramos nossas anotações como RetentionPolicy.RUNTIME. Lembre-se disso pois é importante.

Main.java
 package pkg;  

 import java.lang.annotation.Annotation; 
 import java.lang.reflect.Field; 

 public class Main { 
      public static void main(String[] args) { 
           new Main().exibeValoresAnnotation(); 
      } 

      public void exibeValoresAnnotation(){ 
           Class clazz = Morador.class; 

           if(clazz.isAnnotationPresent(MoradorAnnotation.class)){ 
                Annotation a = clazz.getAnnotation(MoradorAnnotation.class); 
                MoradorAnnotation m = (MoradorAnnotation) a; 
                System.out.printf("Data inicial de moradia: '%s'%n", m.dataInicialMoradia()); 
                System.out.printf("Inquilino: '%s'%n", m.isInquilino()); 
           } 

           for(Field attr : clazz.getDeclaredFields()){ 
                attr.setAccessible(true); 
                if(attr.isAnnotationPresent(CarroAnnotation.class)){ 
                     CarroAnnotation carroAnnotation = (CarroAnnotation) attr.getAnnotation(CarroAnnotation.class); 
                     System.out.printf("Placa: '%s'%n", carroAnnotation.placa()); 
                     System.out.printf("Numeração: '%s'%n", carroAnnotation.numeracaoDocumentoCarro()); 
                } 
           } 
      } 
 } 

Viu como é fácil ? Agora pense que todos aqueles frameworks famosos que você usa, usam essa técnica para classes anotadas. Talvez agora, aquela idéia que você tenha de que os frameworks usam códigos super complexos, não é tão real assim né.

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

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


Referência:
http://pt.wikipedia.org/wiki/Metadados
http://blog.hallanmedeiros.com/2009/06/11/criar-anotacoes-em-java/
http://www.mkyong.com/java/java-custom-annotations-example/
Leia Mais ››

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.

Leia Mais ››