6

Click here to load reader

Enums

Embed Size (px)

Citation preview

  • 1. Enums em Java: utilizao e persistncia Jadson Jos dos Santos [email protected] primeiras verses da linguagem Java, a nica forma que existia para se utilizarconstantes enumeradas era atravs 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 trs.1- pode-se atribuir qualquer valor inteiro para a varivel statusAluno, levando o aluno para ostatus inconsistente.2 No existe uma representao textual direta para as constantes, isto , ao tentar imprimi-las, ser exibido um nmero que no tem significado para o usurio.3 preciso utilizar prefixos nas constantes para indicar a quem elas pertencem.Para solucionar esses problemas, a linguagem Java disponibilizou uma maneira maispoderosa de se definir constantes enumeradas, os enums.public enum StatusAluno { APROVADO, REPROVADO, EM_RECUPERACAO };private StatusAluno status = StatusAluno.APROVADO ;Com a declarao acima, os trs problema citados so solucionados. Somente um dos trsstatus declarados pode ser atribudos varivel status. Ao tenta-se imprimir o valor da varivel, onome declarado da constante ser impresso, no o seu valor numrico. System.out.println(status); // imprime "APROVADO"Os namespace das constantes esto bem definidos dentro do enum StatusAluno.Mas enums so ainda mais poderosos, como as classes, eles podem conter construtores,declaraes de outras variveis e mtodos. Para demostrar o poder do uso dos enums, considere oexemplo da representao da situao de um usurio em um sistema de biblioteca. A princpio,vamos utilizar tipos primitivos para modelar a situao dos usurios.public class ConstantesBiblioteca { // Constantes da situao do Usurio. /** Situao quando o usurio no possui emprstimos em atraso e no est suspenso. */ public static final int SITUACAO_USUARIO_SEM_PENDENCIAS = 0; /** Situao quando o usurio possui emprstimos mas no esto atrasados.*/ public static final int SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATIVOS = 1; /** Situao quando o usurio possui emprstimos e eles esto atrasados.*/

2. public static final int SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATRASADOS = 2; /** Situao quando o usurio est suspenso. */ public static final int SITUACAO_USUARIO_ESTA_SUSPENSO = 3; /** Situao quando o usurio est multado. */ public static final int SITUACAO_USUARIO_ESTA_MULTADO = 4; /** Situao quando o usurio est com emprstimo atrasados. */ public static final int SITUACAO_USUARIO_ESTA_BLOQUEADO = 5;}Vamos imaginar que queremos mostrar essas situaes para o operador do sistema escolher,em um relatrio, quais usurios da biblioteca em uma determinada situao, ele deseja visualizar nomomento. necessrio criar uma listagem para o operador escolher. Essa listagem precisa conter ovalor a ser buscado e a descrio a ser mostradas ao operador. Para pode realizar essa operao,temos que criar uma entidade extra no sistema, que contenha a valor e a descrio de cada possvelsituao do usurio.public class SituacaoUsuarioBiblioteca {/** Retorna o valor inteiro que representa a situao. */private int situacao = -1;/** Descreve a situao que o usurio se encontra */private String descricaoSituacao = null;/** * As possveis situaes de um usurio da biblioteca, preenchidas com descries bsicas. */public static final Set POSSIVEIS_SITUACAO_DO_USUARIO = new HashSet( Arrays.asList(new SituacaoUsuarioBiblioteca[] { new SituacaoUsuarioBiblioteca( ConstantesBiblioteca.SITUACAO_USUARIO_SEM_PENDENCIAS, "Sem Pendncias"), 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 Emprstimos Ativos"), new SituacaoUsuarioBiblioteca( ConstantesBiblioteca.SITUACAO_USUARIO_POSSUI_EMPRESTIMOS_ATRASADOS, "Possui EmprstimosAtrasados"), new SituacaoUsuarioBiblioteca( ConstantesBiblioteca.SITUACAO_USUARIO_ESTA_BLOQUEADO, "Bloqueado") }) );}}Utilizando um enum para modelar a situao do usurio, poderamos ter algo como:public enum SituacaoUsuarioBiblioteca {SEM_PENDENCIA(1, "Usurio Sem Pendncias"),POSSUI_EMPRESTIMOS_ATIVOS(2, "Usurio Possui Emprstimos Ativos"),ESTA_SUSPENSO(3, "Usurio est Suspenso"),ESTA_MULTADO(4, "Usurio est Multado"),POSSUI_EMPRESTIMOS_ATRASADOS(5, "Usurio Possui Emprstimos Atrasados"),ESTA_BLOQUEADO(6, "Usurio est Bloqueado");/** * O valor que representa a situao 3. */ private int valor; /*** A descrio da situao do usurio*/ 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 relatrios*/ public static final Set POSSIVEIS_SITUACAO_DO_USUARIO =new HashSet( Arrays.asList( SituacaoUsuarioBiblioteca.SEM_PENDENCIA, SituacaoUsuarioBiblioteca.ESTA_SUSPENSO,SituacaoUsuarioBiblioteca.ESTA_MULTADO, SituacaoUsuarioBiblioteca.POSSUI_EMPRESTIMOS_ATIVOS, SituacaoUsuarioBiblioteca.POSSUI_EMPRESTIMOS_ATRASADOSSituacaoUsuarioBiblioteca.BLOQUEADO ) );} A varivel esttica POSSIVEIS_SITUACAO_DO_USUARIO do prprio enum j nos retornaria a valor e adescrio das possveis situaes do usurio, sem a necessidade de criar uma nova entidade pararepresentar isso. O que deixa nosso cdigo mais enxuto e legvel. Em vez de fazemos comparaesde 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 prpria constante do enum pode disponibilizar um mtodo que mostre se ela umasituao que permite ao usurio realizar emprstimos na biblioteca, por meio do mtodoisSituacaoImpedeEmprestimos(). Assim nosso cdigo de verificao se resumira a: SituacaoUsuarioBiblioteca situacao = SituacaoUsuarioBiblioteca.ESTA_MULTADO; if(situacao.isSituacaoImpedeEmprestimos()){ } A simplificao do cdigo tambm poderia ser utilizado em pginas web: 4. PersistnciaUm problema que pode-se encontrar com a utilizao de enums com relao a suapersistncia. Como os dados das constantes enumeradas so definidos pelos usurio, no h comoos frameworks de mapeamento objeto relacional saberem de ante mo, como persisti-los. precisoutilizar solues especficas para a implementao JPA utilizada, como por exemplo a interfaceUserType do Hibernate.Para os casos mais comuns, onde o valor das constantes enumeradas representam nmerosinteiros e apenas esse valor precisa ser persistido, possvel utilizar o mapeamento ORDINAL.Esse mapeamento utiliza como valor do enum a ser persistido, o valor sequencial da ordem em queas constantes dos enum so declaradas. Por exemplo, verificaremos o cdigo da entidadeReservaMaterialBiblioteca,que represente uma reserva de um material feita em um sistema debiblioteca.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;}/** Mtodo chamado pelo hibernate para pegar o valor do enum nas consultas HQLs */@Overridepublic 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 so considerados ativos. * * @return */public static StatusReserva[] getReservasAtivas(){ return new StatusReserva[]{StatusReserva.SOLICITADA, StatusReserva.EM_ESPERA};}} 5. A entidade ReservaMaterialBiblioteca contm a declarao do enum pblico1 StatusReserva quepossui uma varivel valor que representa o valor da constantes do enum, um construtor que recebe ovalor da constante e um mdodo toString() que retorna a representao textual do valor da constantedo enum. Essa entidade possui tambm uma varivel status do tipo StatusReserva que mapeada coma anotao @Enumerated com o tipo EnumType.ORDINAL.Assim no momento de realizar a persistncia, O framework de mapeamento objetorelacional vai persistir o valor ordinal das constantes ( comeado do valor zero ) na coluna2correspondente varivel status no banco.A representao textual do enum StatusReserva retornada no mtodo toString(), essarepresentao textual usada para gerar as consultas base de dados.Um exemplo de como realizar consultas utilizando enuns est descrito no mtodofindAllReservasAtivas() mostrado abaixo:/** *

Retorna a listagem de todas as reservas ativas.

* * @param dataSolicitacao * @param idTitulo * @return */public List 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 linhas = q.list();return new ArrayList (HibernateUtils.parseTo(linhas, projecao, ReservaMaterialBiblioteca.class, "r"));}Esse mtodo faz uso do mtodo esttico getReservasAtivas() que retorna um array de todas asreservas que so consideradas ativas no sistema. O valor utilizado na consulta gerada, ser o valorda representao textual do enum retornado pelo mtodo toString(), que a representao textual davarivel valor do enum, que por sua vez, contm o mesmo valor ordinal persistido. Logo, aconsulta acima gerar um SQL do tipo: AND r.status in (1, 2) , retornando as reservas com statusdesejado.1 necessrio ser pblico para o framework JPA conseguir acess-lo.2No banco, a coluna status precisa ser de um tipo que aceite valores inteiros. 6. Refernciashttp://download.oracle.com/javase/1.5.0/docs/guide/language/enums.htmlhttp://www.hibernate.org/265.htmlhttp://www.guj.com.br/java/144147-persistencia-de-enum-enumtypeordinalhttp://www.cs.wustl.edu/~schmidt/CACM-frameworks.htmlhttp://www.java2s.com/Code/Java/JPA/EnumeratedEnumTypeORDINAL.htm