06 Aplicação Web com VRaptor 4 – Criando nosso modelo

Anteriormente neste tutorial . . .

Vimos como configurar o criamos nosso projeto de contatos e criamos o arquivo de configuração persistence.xml.

Lembre-se, já estamos trabalhando no nosso projeto, caso tenha caído neste tutorial acidentalmente, pode ver a lista dos episódios anteriores na pequena introdução que fiz para estes posts. E sempre lembre, você pode, e deve acompanhar os códigos pelo meu github, segue o link ai em baixo:

https://github.com/pedro-hos/aprendendo-vraptor

 Pessoal hoje vamos criar nosso modelos e anota-los para que possam ser criados na nossa base, e assim trabalharmos com eles. Como a ideia destes post não é falar de JPA, não vou fazer um modelo muito grande, ele será bem simples, vou abordar uma ou outra coisa mais elaborada, mas não pretendo entrar em muitos detalhes do, se quiser saber mais sobre JPA, tem um mini livro no blog uaiHebert que aborda muita coisa de JPA, existem também livros e muito conteúdo nas internet.

Para começar, no nosso projeto vamos adicionar uma nova dependência no nosso pom.xml. Com ele aberto adicione o seguinte trecho:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.3.7.Final</version>
    <scope>provided</scope>
</dependency>

Pronto, agora crie uma classe chamada DefaultEntity, ela deve estar dentro do package br.com.pedroHos.model.entities, o conteúdo desta classe é o seguinte:

package br.com.pedroHos.model.entities;

import java.io.Serializable;
import java.time.LocalDateTime;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

@MappedSuperclass
public class DefaultEntity implements Serializable {

    private static final long serialVersionUID = 1L;

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

    @Column(nullable = false)
    private boolean ativo = true;

    @Column(name = "data_criacao", nullable = false)
    private LocalDateTime dataCriacao = LocalDateTime.now();

/*
get e set. So clicar CTRL + 3 no eclipse e depois digitar GGAS
*/

}

A classe acima será usada em todas as outras classes de modelo, ela esta anotada com @MappedSuperclass, para mostrar que toda outra classe que herdar ela deve obrigatoriamente ter os campos dessa classe. O resto da classe é mais comum de ver em outros projetos e tutoriais,

Gostaria de levantar mais um ponto, estamos usando a nova API de data do Java 8, o LocalDateTime, no campo dataCriacao, por isso vamos ter que criar conversor, para que no momento da inserção, ele insira os dados como Date, do pacote java.util, e não um objeto estranho.

Vamos então criar os conversores:

  • Crie package br.com.pedroHos.model.entities.util;
  • Crie a classe LocalDateTimePersistenceConverter dentro do pacote criado anteriormente, o conteúdo da classe é o seguinte:

package br.com.pedroHos.model.entities.util;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter(autoApply = true)
public class LocalDateTimePersistenceConverter implements AttributeConverter<LocalDateTime, Date>{

    @Override
    public Date convertToDatabaseColumn(LocalDateTime localDateTime) {

        if(localDateTime != null) {
            Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
            return Date.from(instant);
        }
        
        return null;
        
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Date dbData) {
        Instant instant = Instant.ofEpochMilli(dbData.getTime());
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }
}

Ali temos a anotação @Converter(autoApply = true), ela implementa AttributeConverter, logo devemos ter dois métodos: convertToDatabaseColumn e o convertToEntityAttribute.

O primeiro pega o valor do atributo da entidade e converte para o tipo da coluna, ou seja, pega o LocalDateTime e converte para Date, bem simples, nada de mais.

O Segundo irá fazer o caminho inverso, ou seja converter de Date, para LocalDateTime. Pronto, isso deve resolver o problema.

[BÔNUS]  Eu criei um conversor para o LocalDate também, vou colocar aqui o código, ele fica no mesmo pacote do anterior ok? E segue o mesmo esquema.


package br.com.pedroHos.model.entities.util;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter(autoApply = true)
public class LocalDatePersistenceConverter implements AttributeConverter<LocalDate, Date> {
    
    @Override
    public Date convertToDatabaseColumn(LocalDate localDate) {
        
        if(localDate != null) {
            Instant instant = localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
            return Date.from(instant);
        }
        
        return null;
    }

    @Override
    public LocalDate convertToEntityAttribute(Date date) {
        
        if(date != null) {
            Instant instant = Instant.ofEpochMilli(date.getTime());
            return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()).toLocalDate();
        }
        
        return null;
    }

}

Agora vamos aos modelos propriamente dita, vamos primeiro criar os Enuns: TipoContato e TipoTelefone.

Ambos dentro do package br.com.pedroHos.model.entities.contato. Dentro deles coloca esses dados:

No TipoContato

package br.com.pedroHos.model.entities.contato;

public enum TipoContato {
    FAMILIA, AMIGO, SERVICO, NAO_CONHECO;
}

No TipoTelefone

package br.com.pedroHos.model.entities.contato;

public enum TipoTelefone {
    CELULAR, FIXO, SERVICO, RADIO, FAX;
}

Pronto, agora vamos criar a classe Telefone, dentro do do mesmo pacote dos Enuns, a classe tem seus atributos, com um relacionamento @ManyToOne com a classe Contato, e também a anotação @Enumerated(EnumType.STRING), para o Enum TipoTelefone, que vamos criar logo adiante. A classe Telefone terá então o seguinte código:


package br.com.pedroHos.model.entities.contato;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

import br.com.pedroHos.model.entities.DefaultEntity;

@Entity
public class Telefone extends DefaultEntity {

private static final long serialVersionUID = 1L;

private String ddd;
private String telefone;

@Enumerated(EnumType.STRING)
@Column(name = "tipo_telefone")
private TipoTelefone TipoTelefone;

@ManyToOne
@JoinColumn(name = "contato_fk")
private Contato contato;

/*
get e set. So clicar CTRL + 3 no eclipse e depois digitar GGAS
*/
}

Por fim a classe Contato, no mesmo pacote das demais, vale ressaltar aqui que as duas classes estendem DefaultEntity, lembram dela? Destaco aqui a relação @OneToMany, que tem mappedBy = “contato”, ou seja estamos falando que na classe Telefone, que tem o atributo contato deve ser o dono do relacionamento, ele deve armazenar a chave do ID do contato, olha lá na classe telefone, vai ter um @JoinColumn(name = “contato_fk”). No final teremos algo como:


package br.com.pedroHos.model.entities.contato;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;

import br.com.pedroHos.model.entities.DefaultEntity;

@Entity
public class Contato extends DefaultEntity {

    private static final long serialVersionUID = 1;
    
    private String nome;
    private String email;
    
    @OneToMany(mappedBy = "contato", fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    private List<Telefone> telefones;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "tipo_contato")
    private TipoContato tipoContato;
/*
get e set. So clicar CTRL + 3 no eclipse e depois digitar GGAS
*/
}

No final você deve ter uma estrutura assim:

Captura de Tela 2015-01-07 às 22.48.18

Agora só subir a aplicação no WildFly, você verá, em caso de sucesso, algo como isso no console:

Captura de Tela 2015-01-07 às 22.50.27

Pronto pessoal era isso, no próximo tutorial, espero falar sobre como trabalhar com os dados na base, inserir, editar, deletar etc 😀 E lembrem de divulgar, e falar se tem algo errado aí!

Anúncios

6 comentários

  1. Pingback: Aplicação Web com VRaptor 4 – Criando nosso Repositório (DAO) | Pedro Hos
  2. Pingback: Aplicação Web com VRaptor 4 – Introdução | Pedro Hos
  3. Pingback: Aplicação Web com VRaptor 4 – Criando nosso Controller | Pedro Hos
  4. Pingback: Aplicação Web com VRaptor 4 – Telefone Controller | Pedro Hos
  5. Ranlive Hrysyk · junho 10, 2015

    Amigo aonde deveria estar mostrando o código da classe Contato está repetindo o código da classe Telefone, ou seja, o código da classe Telefone está sendo mostrada duas vezes e a da classe Contato nenhuma vez.

    • Pedro Henrique de Oliveira Silva · junho 11, 2015

      Obrigado cara. Já arrumei o post. Abraços

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s