SlideShare uma empresa Scribd logo
1 de 6
Baixar para ler offline
Enums em Java: utilização e persistência
                                           Jadson José dos Santos
                                                         jadsonjs@gmail.com


          Nas primeiras versões da linguagem Java, a única forma que existia para se utilizar
constantes enumeradas era através de tipos primitivos:
          public static final int STATUS_ALUNO_APROVADO = 0;
          public static final int STATUS_ALUNO_REPROVADO = 1;
          public static final int STATUS_ALUNO_EM_RECUPERACAO = 2;

          private int statusAluno = STATUS_ALUNO_APROVADO;


          Existem alguns problemas com essa abordagem. Abaixo, enumeram-se apenas três.
          1- pode-se atribuir qualquer valor inteiro para a variável statusAluno, levando o aluno para o
status inconsistente.
          2 – Não existe uma representação textual direta para as constantes, isto é, ao tentar imprimi-
las, será exibido um número que não tem significado para o usuário.
          3 – É preciso utilizar prefixos nas constantes para indicar a quem elas pertencem.
          Para solucionar esses problemas, a linguagem Java disponibilizou uma maneira mais
poderosa de se definir constantes enumeradas, os enums.

          public enum StatusAluno { APROVADO, REPROVADO, EM_RECUPERACAO };

          private StatusAluno status = StatusAluno.APROVADO ;


          Com a declaração acima, os três problema citados são solucionados. Somente um dos três
status declarados pode ser atribuídos à variável status. Ao tenta-se imprimir o valor da variável, o
nome declarado da constante será impresso, não o seu valor numérico.
                     System.out.println(status);   // imprime "APROVADO"


          Os namespace das constantes estão bem definidos dentro do enum StatusAluno.
          Mas enums são ainda mais poderosos, como as classes, eles podem conter construtores,
declarações de outras variáveis e métodos. Para demostrar o poder do uso dos enums, considere o
exemplo da representação da situação de um usuário em um sistema de biblioteca. A princípio,
vamos utilizar tipos primitivos para modelar a situação dos usuários.
public class ConstantesBiblioteca {

           // Constantes da situação do Usuário.

           /** Situação quando o usuário não possui empréstimos em atraso e não está suspenso. */
           public static final int SITUACAO_USUARIO_SEM_PENDENCIAS = 0;

           /** Situação quando o usuário possui empréstimos mas não estão atrasados.*/
           public static final int SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATIVOS = 1;

           /** Situação quando o usuário possui empréstimos e eles estão atrasados.*/
public static final int SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATRASADOS = 2;

           /** Situação quando o usuário está suspenso. */
           public static final int SITUACAO_USUARIO_ESTA_SUSPENSO = 3;

           /** Situação quando o usuário está multado. */
           public static final int SITUACAO_USUARIO_ESTA_MULTADO = 4;

           /** Situação quando o usuário está com empréstimo atrasados. */
           public static final int SITUACAO_USUARIO_ESTA_BLOQUEADO = 5;
}


          Vamos imaginar que queremos mostrar essas situações para o operador do sistema escolher,
em um relatório, quais usuários da biblioteca em uma determinada situação, ele deseja visualizar no
momento.
          É necessário criar uma listagem para o operador escolher. Essa listagem precisa conter o
valor a ser buscado e a descrição a ser mostradas ao operador. Para pode realizar essa operação,
temos que criar uma entidade extra no sistema, que contenha a valor e a descrição de cada possível
situação do usuário.

public class SituacaoUsuarioBiblioteca {

          /** Retorna o valor inteiro que representa a situação. */
          private int situacao = -1;

          /** Descreve a situação que o usuário se encontra */
          private String descricaoSituacao = null;

          /**
           * As possíveis situações de um usuário da biblioteca, preenchidas com descrições básicas.
           */
          public static final Set<SituacaoUsuarioBiblioteca> POSSIVEIS_SITUACAO_DO_USUARIO
                     = new HashSet<SituacaoUsuarioBiblioteca>(
                     Arrays.asList(new SituacaoUsuarioBiblioteca[] {
                     new SituacaoUsuarioBiblioteca(
                                 ConstantesBiblioteca.SITUACAO_USUARIO_SEM_PENDENCIAS, "Sem Pendências"),
                     new SituacaoUsuarioBiblioteca(
                                 ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_SUSPENSO, "Suspenso"),
                     new SituacaoUsuarioBiblioteca(
                                 ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_MULTADO, "Multado"),
                     new SituacaoUsuarioBiblioteca(
                                 ConstantesBiblioteca.SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATIVOS, "Possui Empréstimos Ativos"),
                     new SituacaoUsuarioBiblioteca(
                                 ConstantesBiblioteca.SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATRASADOS, "Possui Empréstimos
Atrasados"),
                     new SituacaoUsuarioBiblioteca(
                                 ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_BLOQUEADO, "Bloqueado") })
                     );
          }
}




          Utilizando um enum para modelar a situação do usuário, poderíamos ter algo como:

public enum SituacaoUsuarioBiblioteca {

          SEM_PENDENCIA(1, "Usuário Sem Pendências"),
          POSSUI_EMPRESTIMOS_ATIVOS(2, "Usuário Possui Empréstimos Ativos"),
          ESTA_SUSPENSO(3, "Usuário está Suspenso"),
          ESTA_MULTADO(4, "Usuário está Multado"),
          POSSUI_EMPRESTIMOS_ATRASADOS(5, "Usuário Possui Empréstimos Atrasados"),
          ESTA_BLOQUEADO(6, "Usuário está Bloqueado");

          /**
           * O valor que representa a situação
*/
       private int valor;

       /**
        * A descrição da situação do usuário
        */
       private String descricao;

       private SituacaoUsuarioBiblioteca(int valor, String descricaoResumida){
         this.valor = valor;
         this.descricao = descricao;
       }

       public boolean isSituacaoImpedeEmprestimos(){
         if(this.equals(ESTA_SUSPENSO) || this.equals(ESTA_MULTADO)
               || this.equals(POSSUI_EMPRESTIMOS_ATRASADOS) || this.equals(ESTA_BLOQUEADO) )
            return true;
         return false;
       }

       /**
        * Usado os relatórios
        */
       public static final Set<SituacaoUsuarioBiblioteca> POSSIVEIS_SITUACAO_DO_USUARIO =
          new HashSet<SituacaoUsuarioBiblioteca>( Arrays.asList(
           SituacaoUsuarioBiblioteca.SEM_PENDENCIA,
           SituacaoUsuarioBiblioteca.ESTA_SUSPENSO,
                  SituacaoUsuarioBiblioteca.ESTA_MULTADO,
           SituacaoUsuarioBiblioteca.POSSUI_EMPRESTIMOS_ATIVOS,
           SituacaoUsuarioBiblioteca.POSSUI_EMPRESTIMOS_ATRASADOS
                  SituacaoUsuarioBiblioteca.BLOQUEADO )
       );
}


       A variável estática POSSIVEIS_SITUACAO_DO_USUARIO do próprio enum já nos retornaria a valor e a
descrição das possíveis situações do usuário, sem a necessidade de criar uma nova entidade para
representar isso. O que deixa nosso código mais enxuto e legível. Em vez de fazemos comparações
de inteiros como mostrado abaixo:


       int situacao = ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_MULTADO;
       if(situacao == ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_SUSPENSO
                   || situacao == ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_MULTADO
                   || situacao == ConstantesBiblioteca.SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATRASADOS
                   || situacao == ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_BLOQUEADO ){

                  }




       A própria constante do enum pode disponibilizar um método que mostre se ela é uma
situação que permite ao usuário realizar empréstimos na biblioteca, por meio do método
isSituacaoImpedeEmprestimos(). Assim           nosso código de verificação se resumira a:


       SituacaoUsuarioBiblioteca situacao = SituacaoUsuarioBiblioteca.ESTA_MULTADO;

       if(situacao.isSituacaoImpedeEmprestimos()){

       }


       A simplificação do código também poderia ser utilizado em páginas web:
<td>
                      <c:if test="${not situacao.situacaoImpedeEmprestimos}">
                                  <h:outputText value="#{situacao.descricao}" style="color:green;"/>
                      </c:if>

                      <c:if test="${ situacao.situacaoImpedeEmprestimos}">
                                  <h:outputText value="#{situacao.descricao}" style="color:red;"/>
                      </c:if>
          </td>




Persistência
          Um problema que pode-se encontrar com a utilização de enums é com relação a sua
persistência. Como os dados das constantes enumeradas são definidos pelos usuário, não há como
os frameworks de mapeamento objeto relacional saberem de ante mão, como persisti-los. É preciso
utilizar soluções específicas para a implementação JPA utilizada, como por exemplo a interface
UserType do Hibernate.
          Para os casos mais comuns, onde o valor das constantes enumeradas representam números
inteiros e apenas esse valor precisa ser persistido, é possível utilizar o mapeamento ORDINAL.
Esse mapeamento utiliza como valor do enum a ser persistido, o valor sequencial da ordem em que
as constantes dos enum são declaradas. Por exemplo, verificaremos o código da entidade
ReservaMaterialBiblioteca,          que represente uma reserva de um material feita em um sistema de
biblioteca.
public class ReservaMaterialBiblioteca {

          public enum StatusReserva {

              SOLICITADA(0), EM_ESPERA(1), CANCELADA(2), CANCELADA_MANUALMENTE(3), CONCRETIZADA(4);

              private int valor;

              private StatusReserva(int valor){
                this.valor = valor;
              }

              /** Método chamado pelo hibernate para pegar o valor do enum nas consultas HQLs */
              @Override
              public String toString() {
                return String.valueOf(valor);
              }
          }

    /**
          * O status da reserva
          */
          @Enumerated(EnumType.ORDINAL)
          @Column(name="status", nullable=false)
          private StatusReserva status = StatusReserva.SOLICITADA;


          /**
    * Retorna os status que são considerados ativos.
           *
           * @return
           */
          public static StatusReserva[] getReservasAtivas(){
             return new StatusReserva[]{StatusReserva.SOLICITADA, StatusReserva.EM_ESPERA};
          }
}
A entidade ReservaMaterialBiblioteca contém a declaração do enum público1 StatusReserva que
possui uma variável valor que representa o valor da constantes do enum, um construtor que recebe o
valor da constante e um médodo toString() que retorna a representação textual do valor da constante
do enum. Essa entidade possui também uma variável status do tipo StatusReserva que é mapeada com
a anotação @Enumerated com o tipo EnumType.ORDINAL.
              Assim no momento de realizar a persistência, O framework de mapeamento objeto
relacional vai persistir o valor ordinal das constantes ( começado do valor zero ) na coluna2
correspondente à variável status no banco.
              A representação textual do enum StatusReserva é retornada no método toString(), essa
representação textual é usada para gerar as consultas à base de dados.
              Um exemplo de como realizar consultas utilizando enuns está descrito no método
findAllReservasAtivas() mostrado abaixo:

    /**
     * <p>Retorna a listagem de todas as reservas ativas. </p>
     *
     * @param dataSolicitacao
     * @param idTitulo
     * @return
     */
    public List<ReservaMaterialBiblioteca> findAllReservasAtivas(int idTitulo, Date dataSolicitacao){

        final String projecao= " r.id, r.dataPrevisaoRetiradaMaterial ";

        StringBuilder hql = new StringBuilder(" SELECT "+projecao);

        hql.append(" FROM ReservaMaterialBiblioteca r ");
        hql.append(" WHERE r.tituloReservado.id = :idTitulo ");
        hql.append(" AND r.status in "        +HibernateUtils.gerarStringIn( ReservaMaterialBiblioteca.getReservasAtivas() ) );
        hql.append(" AND r.dataSolicitacao > :dataSolicitacao");
        hql.append(" ORDER BY r.dataSolicitacao, r.id ");

        Query q = getSession().createQuery(hql.toString());
        q.setInteger("idTitulo", idTitulo);
        q.setTimestamp("dataSolicitacao", dataSolicitacao);

        @SuppressWarnings("unchecked")
        List<Object[]> linhas = q.list();

        return new ArrayList<ReservaMaterialBiblioteca> (
                        HibernateUtils.parseTo(linhas, projecao, ReservaMaterialBiblioteca.class, "r"));
    }




              Esse método faz uso do método estático getReservasAtivas() que retorna um array de todas as
reservas que são consideradas ativas no sistema. O valor utilizado na consulta gerada, será o valor
da representação textual do enum retornado pelo método toString(), que é a representação textual da
variável valor do enum, que por sua vez, contém o mesmo valor ordinal persistido.                                                 Logo,   a
consulta acima gerará um SQL do tipo: AND r.status in (1, 2) , retornando as reservas com status
desejado.


1
    É necessário ser público para o framework JPA conseguir acessá-lo.
2
    No banco, a coluna status precisa ser de um tipo que aceite valores inteiros.
Referências

http://download.oracle.com/javase/1.5.0/docs/guide/language/enums.html

http://www.hibernate.org/265.html

http://www.guj.com.br/java/144147-persistencia-de-enum-enumtypeordinal

http://www.cs.wustl.edu/~schmidt/CACM-frameworks.html

http://www.java2s.com/Code/Java/JPA/EnumeratedEnumTypeORDINAL.htm

Mais conteúdo relacionado

Semelhante a Enums

Curso Java Básico - Aula 03
Curso Java Básico - Aula 03Curso Java Básico - Aula 03
Curso Java Básico - Aula 03Natanael Fonseca
 
Persistência com JPA e Hibernate
Persistência com JPA e HibernatePersistência com JPA e Hibernate
Persistência com JPA e HibernateFernando Oliveira
 
Apostila ph pwamp_parte5
Apostila ph pwamp_parte5Apostila ph pwamp_parte5
Apostila ph pwamp_parte5Ilton Barbosa
 
Apostila PhP com Wamp, 4a Parte
Apostila PhP com Wamp, 4a ParteApostila PhP com Wamp, 4a Parte
Apostila PhP com Wamp, 4a ParteIlton Barbosa
 
Curso de Java (Parte 3)
 Curso de Java (Parte 3) Curso de Java (Parte 3)
Curso de Java (Parte 3)Mario Sergio
 
Usando seu codigo java no mule part 2
Usando seu codigo java no mule part 2Usando seu codigo java no mule part 2
Usando seu codigo java no mule part 2Jeison Barros
 
Curso java 04 - ap is e bibliotecas
Curso java   04 - ap is e bibliotecasCurso java   04 - ap is e bibliotecas
Curso java 04 - ap is e bibliotecasMaurício Linhares
 
Atividades e Intenções (Android)
Atividades e Intenções (Android)Atividades e Intenções (Android)
Atividades e Intenções (Android)Natanael Fonseca
 
Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0
Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0
Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0Elvis Rocha
 
introdução a linguagem java-2003
introdução a linguagem java-2003introdução a linguagem java-2003
introdução a linguagem java-2003elliando dias
 
Curso java 03 - métodos e parâmetros
Curso java   03 - métodos e parâmetrosCurso java   03 - métodos e parâmetros
Curso java 03 - métodos e parâmetrosMaurício Linhares
 
JasperReports Tecnicas de geracao_de_relatorios1
JasperReports  Tecnicas de geracao_de_relatorios1JasperReports  Tecnicas de geracao_de_relatorios1
JasperReports Tecnicas de geracao_de_relatorios1Sliedesharessbarbosa
 

Semelhante a Enums (20)

Curso Java Básico - Aula 03
Curso Java Básico - Aula 03Curso Java Básico - Aula 03
Curso Java Básico - Aula 03
 
Persistência com JPA e Hibernate
Persistência com JPA e HibernatePersistência com JPA e Hibernate
Persistência com JPA e Hibernate
 
Apostila ph pwamp_parte5
Apostila ph pwamp_parte5Apostila ph pwamp_parte5
Apostila ph pwamp_parte5
 
Java13
Java13Java13
Java13
 
Apostila PhP com Wamp, 4a Parte
Apostila PhP com Wamp, 4a ParteApostila PhP com Wamp, 4a Parte
Apostila PhP com Wamp, 4a Parte
 
Aula5
Aula5Aula5
Aula5
 
Curso java script
Curso java scriptCurso java script
Curso java script
 
Imutabilidade
ImutabilidadeImutabilidade
Imutabilidade
 
Curso de Java (Parte 3)
 Curso de Java (Parte 3) Curso de Java (Parte 3)
Curso de Java (Parte 3)
 
Usando seu codigo java no mule part 2
Usando seu codigo java no mule part 2Usando seu codigo java no mule part 2
Usando seu codigo java no mule part 2
 
Curso java 04 - ap is e bibliotecas
Curso java   04 - ap is e bibliotecasCurso java   04 - ap is e bibliotecas
Curso java 04 - ap is e bibliotecas
 
Atividades e Intenções (Android)
Atividades e Intenções (Android)Atividades e Intenções (Android)
Atividades e Intenções (Android)
 
Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0
Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0
Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0
 
05 poo-ii
05   poo-ii05   poo-ii
05 poo-ii
 
introdução a linguagem java-2003
introdução a linguagem java-2003introdução a linguagem java-2003
introdução a linguagem java-2003
 
Aula4
Aula4Aula4
Aula4
 
Mapeamento de herança OR
Mapeamento de herança ORMapeamento de herança OR
Mapeamento de herança OR
 
Curso java 03 - métodos e parâmetros
Curso java   03 - métodos e parâmetrosCurso java   03 - métodos e parâmetros
Curso java 03 - métodos e parâmetros
 
JasperReports Tecnicas de geracao_de_relatorios1
JasperReports  Tecnicas de geracao_de_relatorios1JasperReports  Tecnicas de geracao_de_relatorios1
JasperReports Tecnicas de geracao_de_relatorios1
 
Final e aastract
Final e aastractFinal e aastract
Final e aastract
 

Mais de Jadson Santos

Containerizing a Web Application with Vue.js and Java
Containerizing a Web Application with Vue.js and JavaContainerizing a Web Application with Vue.js and Java
Containerizing a Web Application with Vue.js and JavaJadson Santos
 
Continuous Delivery with Jenkins
Continuous Delivery with JenkinsContinuous Delivery with Jenkins
Continuous Delivery with JenkinsJadson Santos
 
Cd with Github Travis CI and Heroku
Cd with Github Travis CI and HerokuCd with Github Travis CI and Heroku
Cd with Github Travis CI and HerokuJadson Santos
 
Jenkins Continuous Delivery
Jenkins Continuous DeliveryJenkins Continuous Delivery
Jenkins Continuous DeliveryJadson Santos
 
Introduction to angular with a simple but complete project
Introduction to angular with a simple but complete projectIntroduction to angular with a simple but complete project
Introduction to angular with a simple but complete projectJadson Santos
 
Hazelcast Distributed Lock
Hazelcast Distributed LockHazelcast Distributed Lock
Hazelcast Distributed LockJadson Santos
 
Introdução ao Flyway
Introdução ao FlywayIntrodução ao Flyway
Introdução ao FlywayJadson Santos
 
Mini curso gerenciamento de configuração e mudança com GIT + Eclipse - I...
Mini curso gerenciamento de configuração e mudança com GIT + Eclipse  -  I...Mini curso gerenciamento de configuração e mudança com GIT + Eclipse  -  I...
Mini curso gerenciamento de configuração e mudança com GIT + Eclipse - I...Jadson Santos
 
Usando hiberante de forma otimizada
Usando hiberante de forma otimizadaUsando hiberante de forma otimizada
Usando hiberante de forma otimizadaJadson Santos
 
Usando JMeter para testar sua aplicação JSF
Usando JMeter para testar sua aplicação JSFUsando JMeter para testar sua aplicação JSF
Usando JMeter para testar sua aplicação JSFJadson Santos
 
ICEIS 2013 Presentation
ICEIS 2013 PresentationICEIS 2013 Presentation
ICEIS 2013 PresentationJadson Santos
 
Conditional Execution - A Pattern for the Implementation of Fine-Grained Vari...
Conditional Execution - A Pattern for the Implementation of Fine-Grained Vari...Conditional Execution - A Pattern for the Implementation of Fine-Grained Vari...
Conditional Execution - A Pattern for the Implementation of Fine-Grained Vari...Jadson Santos
 

Mais de Jadson Santos (18)

Containerizing a Web Application with Vue.js and Java
Containerizing a Web Application with Vue.js and JavaContainerizing a Web Application with Vue.js and Java
Containerizing a Web Application with Vue.js and Java
 
Continuous Delivery with Jenkins
Continuous Delivery with JenkinsContinuous Delivery with Jenkins
Continuous Delivery with Jenkins
 
Cd with Github Travis CI and Heroku
Cd with Github Travis CI and HerokuCd with Github Travis CI and Heroku
Cd with Github Travis CI and Heroku
 
Vue.js
Vue.jsVue.js
Vue.js
 
Jenkins Continuous Delivery
Jenkins Continuous DeliveryJenkins Continuous Delivery
Jenkins Continuous Delivery
 
Introduction to angular with a simple but complete project
Introduction to angular with a simple but complete projectIntroduction to angular with a simple but complete project
Introduction to angular with a simple but complete project
 
Hazelcast Distributed Lock
Hazelcast Distributed LockHazelcast Distributed Lock
Hazelcast Distributed Lock
 
Bootstrap
BootstrapBootstrap
Bootstrap
 
Testes Unitários
Testes UnitáriosTestes Unitários
Testes Unitários
 
Java8
Java8Java8
Java8
 
Gradle
GradleGradle
Gradle
 
Git
GitGit
Git
 
Introdução ao Flyway
Introdução ao FlywayIntrodução ao Flyway
Introdução ao Flyway
 
Mini curso gerenciamento de configuração e mudança com GIT + Eclipse - I...
Mini curso gerenciamento de configuração e mudança com GIT + Eclipse  -  I...Mini curso gerenciamento de configuração e mudança com GIT + Eclipse  -  I...
Mini curso gerenciamento de configuração e mudança com GIT + Eclipse - I...
 
Usando hiberante de forma otimizada
Usando hiberante de forma otimizadaUsando hiberante de forma otimizada
Usando hiberante de forma otimizada
 
Usando JMeter para testar sua aplicação JSF
Usando JMeter para testar sua aplicação JSFUsando JMeter para testar sua aplicação JSF
Usando JMeter para testar sua aplicação JSF
 
ICEIS 2013 Presentation
ICEIS 2013 PresentationICEIS 2013 Presentation
ICEIS 2013 Presentation
 
Conditional Execution - A Pattern for the Implementation of Fine-Grained Vari...
Conditional Execution - A Pattern for the Implementation of Fine-Grained Vari...Conditional Execution - A Pattern for the Implementation of Fine-Grained Vari...
Conditional Execution - A Pattern for the Implementation of Fine-Grained Vari...
 

Enums

  • 1. Enums em Java: utilização e persistência Jadson José dos Santos jadsonjs@gmail.com Nas primeiras versões da linguagem Java, a única forma que existia para se utilizar constantes enumeradas era através de tipos primitivos: public static final int STATUS_ALUNO_APROVADO = 0; public static final int STATUS_ALUNO_REPROVADO = 1; public static final int STATUS_ALUNO_EM_RECUPERACAO = 2; private int statusAluno = STATUS_ALUNO_APROVADO; Existem alguns problemas com essa abordagem. Abaixo, enumeram-se apenas três. 1- pode-se atribuir qualquer valor inteiro para a variável statusAluno, levando o aluno para o status inconsistente. 2 – Não existe uma representação textual direta para as constantes, isto é, ao tentar imprimi- las, será exibido um número que não tem significado para o usuário. 3 – É preciso utilizar prefixos nas constantes para indicar a quem elas pertencem. Para solucionar esses problemas, a linguagem Java disponibilizou uma maneira mais poderosa de se definir constantes enumeradas, os enums. public enum StatusAluno { APROVADO, REPROVADO, EM_RECUPERACAO }; private StatusAluno status = StatusAluno.APROVADO ; Com a declaração acima, os três problema citados são solucionados. Somente um dos três status declarados pode ser atribuídos à variável status. Ao tenta-se imprimir o valor da variável, o nome declarado da constante será impresso, não o seu valor numérico. System.out.println(status); // imprime "APROVADO" Os namespace das constantes estão bem definidos dentro do enum StatusAluno. Mas enums são ainda mais poderosos, como as classes, eles podem conter construtores, declarações de outras variáveis e métodos. Para demostrar o poder do uso dos enums, considere o exemplo da representação da situação de um usuário em um sistema de biblioteca. A princípio, vamos utilizar tipos primitivos para modelar a situação dos usuários. public class ConstantesBiblioteca { // Constantes da situação do Usuário. /** Situação quando o usuário não possui empréstimos em atraso e não está suspenso. */ public static final int SITUACAO_USUARIO_SEM_PENDENCIAS = 0; /** Situação quando o usuário possui empréstimos mas não estão atrasados.*/ public static final int SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATIVOS = 1; /** Situação quando o usuário possui empréstimos e eles estão atrasados.*/
  • 2. public static final int SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATRASADOS = 2; /** Situação quando o usuário está suspenso. */ public static final int SITUACAO_USUARIO_ESTA_SUSPENSO = 3; /** Situação quando o usuário está multado. */ public static final int SITUACAO_USUARIO_ESTA_MULTADO = 4; /** Situação quando o usuário está com empréstimo atrasados. */ public static final int SITUACAO_USUARIO_ESTA_BLOQUEADO = 5; } Vamos imaginar que queremos mostrar essas situações para o operador do sistema escolher, em um relatório, quais usuários da biblioteca em uma determinada situação, ele deseja visualizar no momento. É necessário criar uma listagem para o operador escolher. Essa listagem precisa conter o valor a ser buscado e a descrição a ser mostradas ao operador. Para pode realizar essa operação, temos que criar uma entidade extra no sistema, que contenha a valor e a descrição de cada possível situação do usuário. public class SituacaoUsuarioBiblioteca { /** Retorna o valor inteiro que representa a situação. */ private int situacao = -1; /** Descreve a situação que o usuário se encontra */ private String descricaoSituacao = null; /** * As possíveis situações de um usuário da biblioteca, preenchidas com descrições básicas. */ public static final Set<SituacaoUsuarioBiblioteca> POSSIVEIS_SITUACAO_DO_USUARIO = new HashSet<SituacaoUsuarioBiblioteca>( Arrays.asList(new SituacaoUsuarioBiblioteca[] { new SituacaoUsuarioBiblioteca( ConstantesBiblioteca.SITUACAO_USUARIO_SEM_PENDENCIAS, "Sem Pendências"), new SituacaoUsuarioBiblioteca( ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_SUSPENSO, "Suspenso"), new SituacaoUsuarioBiblioteca( ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_MULTADO, "Multado"), new SituacaoUsuarioBiblioteca( ConstantesBiblioteca.SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATIVOS, "Possui Empréstimos Ativos"), new SituacaoUsuarioBiblioteca( ConstantesBiblioteca.SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATRASADOS, "Possui Empréstimos Atrasados"), new SituacaoUsuarioBiblioteca( ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_BLOQUEADO, "Bloqueado") }) ); } } Utilizando um enum para modelar a situação do usuário, poderíamos ter algo como: public enum SituacaoUsuarioBiblioteca { SEM_PENDENCIA(1, "Usuário Sem Pendências"), POSSUI_EMPRESTIMOS_ATIVOS(2, "Usuário Possui Empréstimos Ativos"), ESTA_SUSPENSO(3, "Usuário está Suspenso"), ESTA_MULTADO(4, "Usuário está Multado"), POSSUI_EMPRESTIMOS_ATRASADOS(5, "Usuário Possui Empréstimos Atrasados"), ESTA_BLOQUEADO(6, "Usuário está Bloqueado"); /** * O valor que representa a situação
  • 3. */ private int valor; /** * A descrição da situação do usuário */ private String descricao; private SituacaoUsuarioBiblioteca(int valor, String descricaoResumida){ this.valor = valor; this.descricao = descricao; } public boolean isSituacaoImpedeEmprestimos(){ if(this.equals(ESTA_SUSPENSO) || this.equals(ESTA_MULTADO) || this.equals(POSSUI_EMPRESTIMOS_ATRASADOS) || this.equals(ESTA_BLOQUEADO) ) return true; return false; } /** * Usado os relatórios */ public static final Set<SituacaoUsuarioBiblioteca> POSSIVEIS_SITUACAO_DO_USUARIO = new HashSet<SituacaoUsuarioBiblioteca>( Arrays.asList( SituacaoUsuarioBiblioteca.SEM_PENDENCIA, SituacaoUsuarioBiblioteca.ESTA_SUSPENSO, SituacaoUsuarioBiblioteca.ESTA_MULTADO, SituacaoUsuarioBiblioteca.POSSUI_EMPRESTIMOS_ATIVOS, SituacaoUsuarioBiblioteca.POSSUI_EMPRESTIMOS_ATRASADOS SituacaoUsuarioBiblioteca.BLOQUEADO ) ); } A variável estática POSSIVEIS_SITUACAO_DO_USUARIO do próprio enum já nos retornaria a valor e a descrição das possíveis situações do usuário, sem a necessidade de criar uma nova entidade para representar isso. O que deixa nosso código mais enxuto e legível. Em vez de fazemos comparações de inteiros como mostrado abaixo: int situacao = ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_MULTADO; if(situacao == ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_SUSPENSO || situacao == ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_MULTADO || situacao == ConstantesBiblioteca.SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATRASADOS || situacao == ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_BLOQUEADO ){ } A própria constante do enum pode disponibilizar um método que mostre se ela é uma situação que permite ao usuário realizar empréstimos na biblioteca, por meio do método isSituacaoImpedeEmprestimos(). Assim nosso código de verificação se resumira a: SituacaoUsuarioBiblioteca situacao = SituacaoUsuarioBiblioteca.ESTA_MULTADO; if(situacao.isSituacaoImpedeEmprestimos()){ } A simplificação do código também poderia ser utilizado em páginas web:
  • 4. <td> <c:if test="${not situacao.situacaoImpedeEmprestimos}"> <h:outputText value="#{situacao.descricao}" style="color:green;"/> </c:if> <c:if test="${ situacao.situacaoImpedeEmprestimos}"> <h:outputText value="#{situacao.descricao}" style="color:red;"/> </c:if> </td> Persistência Um problema que pode-se encontrar com a utilização de enums é com relação a sua persistência. Como os dados das constantes enumeradas são definidos pelos usuário, não há como os frameworks de mapeamento objeto relacional saberem de ante mão, como persisti-los. É preciso utilizar soluções específicas para a implementação JPA utilizada, como por exemplo a interface UserType do Hibernate. Para os casos mais comuns, onde o valor das constantes enumeradas representam números inteiros e apenas esse valor precisa ser persistido, é possível utilizar o mapeamento ORDINAL. Esse mapeamento utiliza como valor do enum a ser persistido, o valor sequencial da ordem em que as constantes dos enum são declaradas. Por exemplo, verificaremos o código da entidade ReservaMaterialBiblioteca, que represente uma reserva de um material feita em um sistema de biblioteca. public class ReservaMaterialBiblioteca { public enum StatusReserva { SOLICITADA(0), EM_ESPERA(1), CANCELADA(2), CANCELADA_MANUALMENTE(3), CONCRETIZADA(4); private int valor; private StatusReserva(int valor){ this.valor = valor; } /** Método chamado pelo hibernate para pegar o valor do enum nas consultas HQLs */ @Override public String toString() { return String.valueOf(valor); } } /** * O status da reserva */ @Enumerated(EnumType.ORDINAL) @Column(name="status", nullable=false) private StatusReserva status = StatusReserva.SOLICITADA; /** * Retorna os status que são considerados ativos. * * @return */ public static StatusReserva[] getReservasAtivas(){ return new StatusReserva[]{StatusReserva.SOLICITADA, StatusReserva.EM_ESPERA}; } }
  • 5. A entidade ReservaMaterialBiblioteca contém a declaração do enum público1 StatusReserva que possui uma variável valor que representa o valor da constantes do enum, um construtor que recebe o valor da constante e um médodo toString() que retorna a representação textual do valor da constante do enum. Essa entidade possui também uma variável status do tipo StatusReserva que é mapeada com a anotação @Enumerated com o tipo EnumType.ORDINAL. Assim no momento de realizar a persistência, O framework de mapeamento objeto relacional vai persistir o valor ordinal das constantes ( começado do valor zero ) na coluna2 correspondente à variável status no banco. A representação textual do enum StatusReserva é retornada no método toString(), essa representação textual é usada para gerar as consultas à base de dados. Um exemplo de como realizar consultas utilizando enuns está descrito no método findAllReservasAtivas() mostrado abaixo: /** * <p>Retorna a listagem de todas as reservas ativas. </p> * * @param dataSolicitacao * @param idTitulo * @return */ public List<ReservaMaterialBiblioteca> findAllReservasAtivas(int idTitulo, Date dataSolicitacao){ final String projecao= " r.id, r.dataPrevisaoRetiradaMaterial "; StringBuilder hql = new StringBuilder(" SELECT "+projecao); hql.append(" FROM ReservaMaterialBiblioteca r "); hql.append(" WHERE r.tituloReservado.id = :idTitulo "); hql.append(" AND r.status in " +HibernateUtils.gerarStringIn( ReservaMaterialBiblioteca.getReservasAtivas() ) ); hql.append(" AND r.dataSolicitacao > :dataSolicitacao"); hql.append(" ORDER BY r.dataSolicitacao, r.id "); Query q = getSession().createQuery(hql.toString()); q.setInteger("idTitulo", idTitulo); q.setTimestamp("dataSolicitacao", dataSolicitacao); @SuppressWarnings("unchecked") List<Object[]> linhas = q.list(); return new ArrayList<ReservaMaterialBiblioteca> ( HibernateUtils.parseTo(linhas, projecao, ReservaMaterialBiblioteca.class, "r")); } Esse método faz uso do método estático getReservasAtivas() que retorna um array de todas as reservas que são consideradas ativas no sistema. O valor utilizado na consulta gerada, será o valor da representação textual do enum retornado pelo método toString(), que é a representação textual da variável valor do enum, que por sua vez, contém o mesmo valor ordinal persistido. Logo, a consulta acima gerará um SQL do tipo: AND r.status in (1, 2) , retornando as reservas com status desejado. 1 É necessário ser público para o framework JPA conseguir acessá-lo. 2 No banco, a coluna status precisa ser de um tipo que aceite valores inteiros.