Demoiselle Tutorial Módulo 2 Persistência Vanderson Botelho da Silva (SERPRO/SUPST/STCTA) Emerson Sachio Saito (SERPRO/CETEC/CTCTA) Flávio Gomes da Silva Lisboa (SERPRO/CETEC/CTCTA) Serge Normando Rehem (SERPRO/CETEC/CTSDR) 18 de março de 2010 1 Laboratório 2 - Persistência Este laboratório tem por objetivo fixar os conceitos da camada de persistência do Framework Demoiselle e orientar o processo de configuração das aplicações. Os objetivos específicos desse laboratório são: Configurar a camada de persistência através do Demoiselle Wizard; Criar a camada de persistência da aplicação Escola; Interfaces DAO Implementações DAO; Filtros de Consulta; Testar o funcionamento da camada de persistência. 1.1 Configuração do Projeto Este laboratório utilizará o projeto escola criado no laboratório anterior. 1. Clique com o botão direito sobre o projeto e acione a opção Demoiselle Configurar Projeto. Figura 1: Configurar Projeto 2. Na guia Hibernate, configure os campos conforme seu banco de dados. Este tutorial utilizará como exemplo o HypersonicSQL. Altere as seguintes informações: URL: jdbc:hsqldb:hsql://127.0.0.1/escola Usuário: sa 1
Figura 2: Configuração da conexão com o banco de dados Figura 3: hibernate.cfg.xml 3. Clique no botão Finish. O Wizard irá configurar o hibernate.cfg.xml na pasta de resources do projeto conforme Figura 3 4. Adicione a dependência do HSQLDB versão 1.8.0.1 no arquivo pom.xml da aplicação (logo após a tag <profiles>) conforme a listagem abaixo: <d e p e ndencies>... <dependency> <groupid>hsqldb</ groupid> <a r t i f a c t I d>hsqldb</ a r t i f a c t I d> <v e r s i o n>1. 8. 0. 1</ v e r s i o n> </ dependency>... </ d e p e ndencies> 2
1.2 Desenvolvimento da camada de persistência Feita a configuração da aplicação para acesso ao banco de dados, o próximo passo é a implementação efetiva da camada de persistência. 1.2.1 Pacote Bean 1. No pacote br.gov.demoiselle.bean implemente o Pojo Aluno conforme abaixo: Listing 1: Aluno.java package br. gov. d e m o i s e l l e. e s c o l a. bean ; import java. u t i l. ArrayList ; import java. u t i l. Date ; import java. u t i l. HashSet ; import java. u t i l. L i s t ; import java. u t i l. Set ; import javax. p e r s i s t e n c e. Entity ; import javax. p e r s i s t e n c e. Table ; import javax. p e r s i s t e n c e. Column ; import javax. p e r s i s t e n c e. FetchType ; import javax. p e r s i s t e n c e. GeneratedValue ; import javax. p e r s i s t e n c e. Id ; import javax. p e r s i s t e n c e. Temporal ; import javax. p e r s i s t e n c e. TemporalType ; import javax. p e r s i s t e n c e. CascadeType ; import javax. p e r s i s t e n c e. OneToMany ; import javax. p e r s i s t e n c e. GenerationType ; import br. gov. framework. d e m o i s e l l e. c o r e. bean. IPojo ; @Entity @Table ( name= aluno ) @SequenceGenerator ( name= AlunoSequence, sequencename= a l u n o s e q, a l l o c a t i o n S i z e =1) p u b l i c c l a s s Aluno implements IPojo { p r i v a t e s t a t i c f i n a l long s e r i a l V e r s i o n U I D = 1L ; @Id @GeneratedValue ( g e n e r a t o r= AlunoSequence, @Column( name= i d a l u n o ) p r i v a t e Long i d ; s t r a t e g y=generationtype.sequence) @Column( name= nome, l e n g t h =100) p r i v a t e S t r i n g nome ; @Column( name= pai, l e n g t h =100) p r i v a t e S t r i n g pai ; @Column( name= mae, l e n g t h =100) p r i v a t e S t r i n g mae ; @Column( name= nascimento ) @Temporal ( value=temporaltype.date) p r i v a t e Date nascimento ; @OneToMany( cascade=cascadetype. ALL, p r i v a t e Set<Endereco> e n d e r e c o s ; f e t c h=fetchtype.lazy) p u b l i c Aluno ( ) { 3
e n d e r e c o s = new HashSet<Endereco >(); p u b l i c Aluno ( long i d ) { t h i s ( ) ; t h i s. i d = i d ; p u b l i c Long g e t I d ( ) { r e t u r n i d ; p u b l i c void s e t I d ( Long i d ) { t h i s. i d = i d ; p u b l i c S t r i n g getnome ( ) { r e t u r n nome ; p u b l i c void setnome ( S t r i n g nome ) { t h i s. nome = nome ; p u b l i c S t r i n g getpai ( ) { r e t u r n pai ; p u b l i c void s e t P a i ( S t r i n g pai ) { t h i s. pai = pai ; p u b l i c S t r i n g getmae ( ) { r e t u r n mae ; p u b l i c void setmae ( S t r i n g mae) { t h i s. mae = mae ; p u b l i c Date getnascimento ( ) { r e t u r n nascimento ; p u b l i c void setnascimento ( Date nascimento ) { t h i s. nascimento = nascimento ; p u b l i c Set<Endereco> getenderecos ( ) { r e t u r n e n d e r e c o s ; p u b l i c L i s t <Endereco> g e t L i s t a E n d e r e c o ( ) { r e t u r n new ArrayList <Endereco >( e n d e r e c o s ) ; p u b l i c void s e t E n d e r e c o s ( Set<Endereco> e n d e r e c o s ) { t h i s. e n d e r e c o s = e n d e r e c o s ; 2. No mesmo pacote, implemente o Pojo Endereco conforme listagem abaixo: Listing 2: Endereco.java package br. gov. d e m o i s e l l e. e s c o l a. bean ; import javax. p e r s i s t e n c e. Column ; import javax. p e r s i s t e n c e. Entity ; import javax. p e r s i s t e n c e. FetchType ; import javax. p e r s i s t e n c e. GeneratedValue ; import javax. p e r s i s t e n c e. GenerationType ; import javax. p e r s i s t e n c e. Id ; import javax. p e r s i s t e n c e. JoinColumn ; import javax. p e r s i s t e n c e. ManyToOne ; import javax. p e r s i s t e n c e. Table ; import br. gov. component. d e m o i s e l l e. common. pojo. e x t e n s i o n. D e s c r i p t i o n ; import br. gov. component. d e m o i s e l l e. common. pojo. e x t e n s i o n. E q u a l s F i e l d ; import br. gov. component. d e m o i s e l l e. common. pojo. e x t e n s i o n. PojoExtension ; import br. gov. framework. d e m o i s e l l e. c o r e. bean. IPojo ; @Entity @Table ( name= endereco ) @SequenceGenerator ( name= EnderecoSequence, sequencename= Endereco seq, a l l o c a t i o n S i z e =1) 4
p u b l i c c l a s s Endereco extends PojoExtension implements IPojo { p r i v a t e s t a t i c f i n a l long s e r i a l V e r s i o n U I D = 1L ; @ EqualsField @Id @GeneratedValue ( g e n e r a t o r= EnderecoSequence, @Column( name= i d e n d e r e c o ) p r i v a t e Long i d ; s t r a t e g y=generationtype.sequence) @ EqualsField @ Description @Column( name= l o g r a d o u r o, l e n g t h =100) p r i v a t e S t r i n g l o g r a d o u r o ; @ Description @Column( name= numero, l e n g t h =100) p r i v a t e S t r i n g numero ; @ Description @Column( name= complemento, l e n g t h =100) p r i v a t e S t r i n g complemento ; @ Description @Column( name= b a i r r o, l e n g t h =100) p r i v a t e S t r i n g b a i r r o ; @ Description @Column( name= cep, l e n g t h =100) p r i v a t e S t r i n g cep ; @Column( name= municipio, l e n g t h =100) p r i v a t e S t r i n g municipio ; @ Description @Column( name= t i p o ) p r i v a t e I n t e g e r t i p o ; @ Description @ManyToOne( f e t c h=fetchtype.lazy) @JoinColumn ( name= aluno ) p r i v a t e Aluno aluno ; p u b l i c Endereco ( ) { p u b l i c Endereco ( S t r i n g logradouro, S t r i n g numero, S t r i n g complemento, S t r i n g b a i r r o, S t r i n g cep, S t r i n g Municipio, I n t e g e r t i p o ) { super ( ) ; t h i s. l o g r a d o u r o = l o g r a d o u r o ; t h i s. numero = numero ; t h i s. complemento = complemento ; t h i s. b a i r r o = b a i r r o ; t h i s. cep = cep ; t h i s. municipio = Municipio ; t h i s. t i p o = t i p o ; p u b l i c Long g e t I d ( ) { r e t u r n i d ; p u b l i c void s e t I d ( Long i d ) { 5
t h i s. i d = i d ; p u b l i c S t r i n g getlogradouro ( ) { r e t u r n l o g r a d o u r o ; p u b l i c void setlogradouro ( S t r i n g l o g r a d o u r o ) { t h i s. l o g r a d o u r o = l o g r a d o u r o ; p u b l i c S t r i n g getnumero ( ) { r e t u r n numero ; p u b l i c void setnumero ( S t r i n g numero ) { t h i s. numero = numero ; p u b l i c S t r i n g getcomplemento ( ) { r e t u r n complemento ; p u b l i c void setcomplemento ( S t r i n g complemento ) { t h i s. complemento = complemento ; p u b l i c S t r i n g g e t B a i r r o ( ) { r e t u r n b a i r r o ; p u b l i c void s e t B a i r r o ( S t r i n g b a i r r o ) { t h i s. b a i r r o = b a i r r o ; p u b l i c S t r i n g getcep ( ) { r e t u r n cep ; p u b l i c void setcep ( S t r i n g cep ) { t h i s. cep = cep ; p u b l i c I n t e g e r gettipo ( ) { r e t u r n t i p o ; p u b l i c void settipo ( I n t e g e r t i p o ) { t h i s. t i p o = t i p o ; p u b l i c S t r i n g getmunicipio ( ) { r e t u r n municipio ; p u b l i c void s e t M u n i c i p i o ( S t r i n g Municipio ) { t h i s. municipio = Municipio ; p u b l i c Aluno getaluno ( ) { r e t u r n aluno ; 6
p u b l i c void setaluno ( Aluno aluno ) { t h i s. aluno = aluno ; 3. Para associar os Pojos ao hibernate.cfg.xml acione o menu Demoiselle Configurar Projeto Na guia Hibernate, clique no botão Adicionar Pojo (Figura 4). Figura 4: Adicionar Pojo Na tela seguinte (Figura 5), seleciona a classe que deseja associar. Acione o botão Finish e verifique que o Wizard associou o arquivo hibernate.cfg.xml aos dois arquivos hbm: Listing 3: Endereco.java <property name= h i b e r n a t e. c o n n e c t i o n. d r i v e r c l a s s > org. hsqldb. j d b c D r i v e r </ property> <property name= h i b e r n a t e. c o n n e c t i o n. u r l > j d b c : h s q l d b : h s q l : // l o c a l h o s t / e s c o l a / </ property> <property name= h i b e r n a t e. c o n n e c t i o n. username > sa </ property> <property name= h i b e r n a t e. c o n n e c t i o n. password /> <property name= h i b e r n a t e. d i a l e c t > org. h i b e r n a t e. d i a l e c t. HSQLDialect 7
Figura 5: Seleção de Pojos </ property> <property name= s h o w s q l > t r u e </ property> <property name= f o r m a t s q l > t r u e </ property> <property name= hbm2ddl. auto > update </ property> <mapping c l a s s= br. gov. d e m o i s e l l e. e s c o l a. bean. Aluno /> <mapping c l a s s= br. gov. d e m o i s e l l e. e s c o l a. bean. Endereco /> 1.2.2 Implementação dos pacotes DAO 1. Para a geração das classes de acesso a dados (DAO), utilize o Demoiselle Editar Projeto, como mostrado na Figura 6 2. Na guia DAOs acione o botão Adicionar para criar o DAO responsável pelo Pojo Aluno 3. No campo Pacote selecione o pacote br.gov.demoiselle.persistence.dao 4. No campo Pojo selecione a classe br.gov.demoiserlle.escola.bean.aluno 8
Figura 6: Editar Projeto Figura 7: Adicionar DAO 5. Selecione o tipo de DAO Hibernate conforme mostrado na Figura 8 6. Acione o botão Finish e aguarde a criação das classes conforme a Figura 9 A classe IAlunoDAO especifica apenas os métodos de consulta. Adicione na interface IAlunoDAO os seguintes métodos: Listing 4: IAlunoDAO.java package br. gov. d e m o i s e l l e. e s c o l a. p e r s i s t e n c e. dao ; import java. u t i l. L i s t ; import br. gov. framework. d e m o i s e l l e. c o r e. l a y e r.idao; import br. gov. framework. d e m o i s e l l e. u t i l. page. Page ; import br. gov. framework. d e m o i s e l l e. u t i l. page. PagedResult ; import br. gov. d e m o i s e l l e. e s c o l a. bean. Aluno ; import br. gov. d e m o i s e l l e. e s c o l a. bean. Endereco ; p u b l i c i n t e r f a c e IAlunoDAO extends IDAO<Aluno> { 9
Figura 8: Salvar DAO Figura 9: Interface para DAO e sua implementação p u b l i c PagedResult<Aluno> l i s t a r ( Page pagina ) ; p u b l i c L i s t <Aluno> l i s t a r ( ) ; p u b l i c PagedResult<Aluno> f i l t r a r ( Aluno aluno, Page pagina ) ; p u b l i c Aluno buscar ( Aluno aluno ) ; p u b l i c void a l t e r a r E n d e r e c o ( Endereco endereco ) ; A classe AlunoDAO implementará apenas os métodos definidos pela interface IAlunoDAO, pois as demais operações (Create Read Update Delete) encontram-se implementadas por herança. Por enquanto, crie os métodos da classe AlunoDAO sem implementação: Listing 5: AlunoDAO.java import java. u t i l. L i s t ; import br. gov. framework. d e m o i s e l l e. p e r s i s t e n c e. h i b e r n a t e. HibernateGenericDAO ; import br. gov. framework. d e m o i s e l l e. u t i l. page. Page ; import br. gov. framework. d e m o i s e l l e. u t i l. page. PagedResult ; import br. gov. d e m o i s e l l e. e s c o l a. bean. Aluno ; import br. gov. d e m o i s e l l e. e s c o l a. bean. Endereco ; import br. gov. d e m o i s e l l e. e s c o l a. p e r s i s t e n c e. dao. IAlunoDAO ; p u b l i c c l a s s AlunoDAO extends HibernateGenericDAO<Aluno> implements IAlunoDAO { p u b l i c void a l t e r a r E n d e r e c o ( Endereco endereco ) { // TODO Auto gen era ted method s t u b p u b l i c L i s t <Aluno> l i s t a r ( ) { // TODO Auto gen era ted method s t u b r e t u r n n u l l ; p u b l i c Aluno buscar ( Aluno aluno ) { // TODO Auto gen era ted method s t u b 10
r e t u r n n u l l ; p u b l i c PagedResult<Aluno> f i l t r a r ( Aluno aluno, Page pagina ) { // TODO Auto gen erat ed method s t u b r e t u r n n u l l ; p u b l i c PagedResult<Aluno> l i s t a r ( Page pagina ) { // TODO Auto gen erat ed method s t u b r e t u r n n u l l ; 1.2.3 Filtros - Uso do componente 1. No pacote br.gov.demoiselle.escola.persistence.dao.filter crie a classe FiltroAluno e inclua os camos ID e NOME para a filtragem conforme Listagem 6 Listing 6: FiltroAluno.java package br. gov. d e m o i s e l l e. e s c o l a. p e r s i s t e n c e. dao. f i l t e r ; import br. gov. component. d e m o i s e l l e. h i b e r n a t e. f i l t e r. F i l t e r ; import br. gov. d e m o i s e l l e. e s c o l a. bean. Aluno ; p u b l i c c l a s s F i l t r o A l u n o extends F i l t e r { p r i v a t e s t a t i c f i n a l long s e r i a l V e r s i o n U I D = 1L ; p u b l i c s t a t i c f i n a l S t r i n g ID = i d ; p u b l i c s t a t i c f i n a l S t r i n g NOME = nome ; p u b l i c F i l t r o A l u n o ( ) { s e t C l a z z ( Aluno. c l a s s ) ; addorder (NOME, ASC ) ; 2. Para utilizar o componente Hibernate Filter, as classes DAOs deverão extender a classe HibernateFilterGenericDAO. Para isso, faça o seguinte: Modifique a classe AlunoDAO de: p u b l i c c l a s s AlunoDAO extends HibernateGenericDAO<Aluno> implements IAlunoDAO para: p u b l i c c l a s s AlunoDAO extends HibernateFilterGenericDAO<Aluno> implements IAlunoDAO Substitua linha: import br. gov. framework. d e m o i s e l l e. p e r s i s t e n c e. h i b e r n a t e. HibernateGenericDAO ; por: import br. gov. component. d e m o i s e l l e. h i b e r n a t e. f i l t e r. dao. HibernateFilterGenericDAO ; import br. gov. framework. d e m o i s e l l e. p e r s i s t e n c e. h i b e r n a t e. H i b e r n a t e U t i l ; import br. gov. d e m o i s e l l e. e s c o l a. p e r s i s t e n c e. dao. f i l t e r. F i l t r o A l u n o ; 3. Implemente os métodos da classe AlunoDAO conforme abaixo: 11
Listar alunos: p u b l i c PagedResult<Aluno> l i s t a r ( Page pagina ) { H i b e r n a t e U t i l. g e t I n s t a n c e ( ). g e t S e s s i o n ( ). f l u s h ( ) ; r e t u r n findhql ( FROM Aluno ORDER BY nome ASC, pagina ) ; p u b l i c L i s t <Aluno> l i s t a r ( ) { H i b e r n a t e U t i l. g e t I n s t a n c e ( ). g e t S e s s i o n ( ). f l u s h ( ) ; r e t u r n findhql ( FROM Aluno ORDER BY nome ASC ) ; 4. Filtrar alunos: p u b l i c PagedResult<Aluno> f i l t r a r ( Aluno aluno, Page pagina ) { H i b e r n a t e U t i l. g e t I n s t a n c e ( ). g e t S e s s i o n ( ). f l u s h ( ) ; r e t u r n findbyexample ( aluno, pagina ) ; 5. Buscar alunos: p u b l i c Aluno buscar ( Aluno aluno ) { H i b e r n a t e U t i l. g e t I n s t a n c e ( ). g e t S e s s i o n ( ). f l u s h ( ) ; F i l t r o A l u n o f i l t r o = new F i l t r o A l u n o ( ) ; f i l t r o. addequals ( F i l t r o A l u n o. ID, aluno. g e t I d ( ) ) ; L i s t <Aluno> r e t o r n o = f i n d ( f i l t r o ) ; i f ( r e t o r n o!= n u l l && r e t o r n o. s i z e ( ) > 0 ) r e t u r n r e t o r n o. get ( 0 ) ; r e t u r n n u l l ; 6. Alterar endereço: p u b l i c void a l t e r a r E n d e r e c o ( Endereco endereco ) { H i b e r n a t e U t i l. g e t I n s t a n c e ( ). g e t S e s s i o n ( ). update ( endereco ) ; Sua camada de acesso a dados está implementada e pronta para ser testada! 1.3 Execução e testes 1. Para realizar os testes, utilizaremos o banco de dados HSQLDB, que foi incluído como dependência. 2. Para realizar os testes, podemos utilizar o banco de dados HSQLDB disponível no material de treinamento. (repositório SVN do Demoiselle: https://demoiselle.svn.sourceforge.net/svnroot/demoiselle/trunk/ docs/others/tutorial/tools/hsqldb.zip) 3. Inicie-o em modo servidor da seguinte forma: Se ambiente Windows: execute o arquivo./hsqldb/run.bat Se ambiente Linux: execute o arquivo./hsqldb/run.sh Mantenha o console aberto equanto utilizar o banco. método, ignore o próximo item. Se utilizar este 12
Figura 10: Console de inicialização do HSQLDB 4. Para iniciar o banco através do Eclipse, inicie-o em modo servidor da seguinte forma: No ambiente Eclipse, crie o arquivo server.properties na raiz do projeto, contendo as propriedades mostradas na Figura 11. Figura 11: Configuração do Banco Escola Selecione o menu run Run Configurations... Na janema que se abre (Figura 12), clique com o botão direito do mouse em Java Application New Na tela seguinte (Figura 13), clique no botão Search. Na tela seguinte (Figura 14), digite ou procure o item Server e depois clique em OK. Ao voltar na tela anterior (Figura 13), dê um nome para a configuração (no campo Name), clique no botão Apply e depois Run. Com isto, toda vez que precisar executar o banco de dados, basta escolher esta configuração. O HSQLDB vem com uma ferramenta chamada Database Manager, que é uma interface gráfica que permite navegar pelas tabelas do banco. É 13
Figura 12: Run configurations muito útil para acompanhar o efeito das operações de persistência. Ela pode ser executada com o comando: java -cp hsqldb/lib/hsqldb.jar org.hsqldb.util.databasemanager 5. Para geração das classes de testes da camada DAO, utilize o menu Demoiselle Editar Projeto (Figura 6) Selecione a aba Teste Unitário (Figura 15) Clique no botão Adicionar, para habilitar a inclusão de um novo teste unitário e os campos do lado direito da tela. Clique no botão Pesquisar, por padrão o Tipo de Interface já estará marcado como DAO, e será deste tipo que iremos criar o teste. Na tela que se abre (Figura 16), seleciona a interface IAlunoDAO e clique no botão Finish. Com a interface selecionada, clique no botão Salvar (Figura 17) Em seguida, clique no botão Aplicar (Figura 18) Aguarde a confirmação dos resultados (Figura 19) Depois clique no botão Finish. O caso de testes deve ser criado conforme a estrutura mostrada na Figura 20 6. Altere o teste para inclusão do Aluno: p u b l i c void t e s t I n s e r t O b j e c t ( ) { Aluno obj Aluno = new Aluno ( ) ; obj Aluno. setnome ( Aluno 01 ) ; obj Aluno. setnascimento ( new Date ( ) ) ; obj Aluno. setmae ( Mae do aluno 01 ) ; obj Aluno. s e t P a i ( Pai do aluno 01 ) ; 14
Figura 13: New configuration Endereco obj Endereco = new Endereco ( ) ; obj Endereco. s e t B a i r r o ( B a i r r o do aluno 01 ) ; obj Endereco. setcep ( 01010101 ) ; obj Endereco. setcomplemento ( Complementdo ao Aluno 01 ) ; obj Endereco. setlogradouro ( Logra ) ; obj Endereco. setaluno ( obj Aluno ) ; obj Aluno. s e t E n d e r e c o s ( new HashSet<Endereco > ( ) ) ; obj Aluno. getenderecos ( ). add ( obj Endereco ) ; alunodao. i n s e r t ( obj Aluno ) ; a s s e r t T r u e ( obj Aluno. g e t I d ( ) >= 0 ) ; Endereco endereco = ( Endereco ) obj Aluno. getenderecos ( ). toarray ( ) [ 0 ] ; a s s e r t N o t N u l l ( endereco ) ; a s s e r t T r u e ( endereco. g e t I d ( ) >= 0 ) ; Para este teste serão necessários os seguintes imports: import java. u t i l. Date ; import java. u t i l. HashSet ; import br. gov. d e m o i s e l l e. e s c o l a. bean. Aluno ; import br. gov. d e m o i s e l l e. e s c o l a. bean. Endereco ; 7. Altere o teste de alteração do Aluno: @Test p u b l i c void testupdate ( ) { // Cria um novo aluno Aluno obj Aluno = new Aluno ( ) ; obj Aluno. setnome ( A l u n o c r i a d o ) ; Endereco endereco = new Endereco ( ) ; endereco. setlogradouro ( E n d e r e c o c r i a d o ) ; 15
Figura 14: Server configuration endereco. setaluno ( obj Aluno ) ; obj Aluno. s e t E n d e r e c o s ( new HashSet<Endereco > ( ) ) ; obj Aluno. getenderecos ( ). add ( endereco ) ; alunodao. i n s e r t ( obj Aluno ) ; long i d = obj Aluno. g e t I d ( ) ; // A l t e r a o aluno c r i a d o obj Aluno = alunodao. buscar ( new Aluno ( i d ) ) ; obj Aluno. setnome ( A l u n o a l t e r a d o ) ; endereco = ( Endereco ) obj Aluno. getenderecos ( ). toarray ( ) [ 0 ] ; endereco. setlogradouro ( E n d e r e c o a l t e r a d o ) ; alunodao. update ( obj Aluno ) ; // Consulta aluno a l t e r a d o obj Aluno = alunodao. buscar ( new Aluno ( i d ) ) ; a s s e r t E q u a l s ( A l u n o a l t e r a d o, obj Aluno. getnome ( ) ) ; endereco = ( Endereco ) obj Aluno. getenderecos ( ). toarray ( ) [ 0 ] ; endereco. setlogradouro ( E n d e r e c o a l t e r a d o ) ; a s s e r t E q u a l s ( E n d e r e c o a l t e r a d o, endereco. getlogradouro ( ) ) ; 8. Altere o método para teste de remoção de Aluno: @Test p u b l i c void testremove ( ) { // Cria um aluno para s e r removido Aluno obj Aluno = new Aluno ( ) ; obj Aluno. setnome ( A l u n o c r i a d o ) ; Endereco endereco = new Endereco ( ) ; endereco. setlogradouro ( E n d e r e c o c r i a d o ) ; endereco. setaluno ( obj Aluno ) ; obj Aluno. s e t E n d e r e c o s ( new HashSet<Endereco > ( ) ) ; obj Aluno. getenderecos ( ). add ( endereco ) ; alunodao. i n s e r t ( obj Aluno ) ; 16
Figura 15: Aba Teste Unitário long i d = obj Aluno. g e t I d ( ) ; //Remove o aluno obj Aluno = alunodao. buscar ( new Aluno ( i d ) ) ; a s s e r t N o t N u l l ( obj Aluno ) ; alunodao. remove ( obj Aluno ) ; // V e r i f i c a se f o i removido obj Aluno = alunodao. buscar ( new Aluno ( i d ) ) ; a s s e r t N u l l ( obj Aluno ) ; 9. Altere também o teste para o método de consulta: @Test p u b l i c void t e s t L i s t a r L i s t ( ) { L i s t <Aluno> l i s t a = new ArrayList <Aluno >(); l i s t a = alunodao. l i s t a r ( ) ; f o r ( Aluno v a r i o s : l i s t a ) { System. out. p r i n t l n ( v a r i o s. g e t I d ( ) ) ; a s s e r t T r u e ( l i s t a. s i z e () >0); 10. Para este teste, serão necessários os seguintes imports: import java. u t i l. L i s t ; import java. u t i l. ArrayList ; Observação: O teste de listagem só terá sucesso se estiver após o teste de inclusão. Ou ainda após a primeira execução dos teste. 17
Figura 16: Seleção de interface para implementação de teste unitário 11. Os outros teste estarão como asserttrue( false ); e, portanto, deverão falhar. Para o exercício proposto, os testes que foram implementados são suficientes para testar a camada DAO. 12. Após as alterações execute o comando Clean acionado pelo menu Project Clean... 13. Execute os testes, como indicado na Figura 21, e verifique os seus resultados. Perceba que os testes implementados ocorreram com sucesso. 1.4 Criação de DAO Stub e Fábrica Customizada 1. Criar uma nova implementação para a interface IAlunoDAO chamada AlunoDAOStub. Esta classe armazenará os dados em memória. Dica: p u b l i c c l a s s AlunoDAOStub implements IAlunoDAO { continue... p r i v a t e s t a t i c L i s t <Aluno> l i s t A l u n o = new ArrayList <Aluno >(); p r i v a t e s t a t i c Long idaluno = 0 l ; p r i v a t e s t a t i c Long idendereco = 0 l ; 2. Duplique a classe AlunoDAOTest com o novo nome AlunoDAOStubTest, altere apenas a notação do atributo IAlunoDAO conforme listagem abaixo: p u b l i c c l a s s AlunoDAOStubTest implements IFacade { @ I n j e c t i o n ( name= br. gov. d e m o i s e l l e. e s c o l a. p e r s i s t e n c e. dao. implementation. AlunoDA p r i v a t e IAlunoDAO alunodao ; 3. Rode os testes e verifique seus resultados. 18
Figura 17: Criação de teste unitário com interface DAO selecionada 4. Para a criação da fábrica customizada de DAOs, crie um pacote factory dentro do pacote persistence: package br. gov. d e m o i s e l l e. e s c o l a. p e r s i s t e n c e. f a c t o r y ; 5. Crie a classe EscolaDAOFactory no pacote criado: p u b l i c c l a s s EscolaDAOFactory extends WebDAOFactory { @SuppressWarnings ( unchecked ) p u b l i c IDAO c r e a t e ( I n j e c t i o n C o n t e x t ctx ) { IDAO newdao = n u l l ; S t r i n g classname = ctx. getfieldtype ( ). getname ( ) ; classname = classname. r e p l a c e (. dao.,. dao. implementation. ) ; classname = classname. r e p l a c e (. I,. ) ; classname += Stub ; t r y { C l a s s c = C l a s s. forname ( classname ) ; newdao = (IDAO) c. newinstance ( ) ; catch ( Exception e ) { throw new RuntimeException ( e ) ; r e t u r n newdao ; 6. Volte à classe AlunoDAOStubTest, inclua a anotação @Factory para indicar que esta classe utilizará a fábrica customizada e volte a utilizar apenas o @Injection no atributo alunodao. 19
Figura 18: Aplicando modificações dos testes unitários Figura 19: Janela de confirmação de criação dos testes unitários @Factory ( f a c t o r y=escoladaofactory. c l a s s ) p u b l i c c l a s s AlunoDAOStubTest implements IFacade { @ I n j e c t i o n p r i v a t e IAlunoDAO alunodao ; 7. Rode os testes de unidade e verifique os resultados. Sugestão de Execício - Implementar os testes restantes. 20
Figura 20: Estrutura de pacotes mostrando o teste unitário para AlunoDAO Figura 21: Execução dos testes 21