Lista de Códigos
7.4 Mapeamento objeto-relacional
Além da vantagem mencionada no parágrafo anterior, pode-se citar também as seguintes vantagens da utilização deDAOs:
• Pode ser usada em uma vasta porcentagem de aplicações;
• Esconde todos os detalhes relativos a armazenamento de dados do resto da aplicação;
• Atua como um intermediário entre a aplicação e o banco de dados;
• Mitiga ou resolve problemas de comunicação entre a base de dados e a aplicação, evitando estados inconsistentes de dados.
No contexto específico da linguagem de programação Java, um DAO pode ser implementado de várias maneiras. Pode variar desde uma simples interface que separa partes de acesso a dados da lógica de negócio de uma aplicação até frameworks e produtos comerciais específicos tais como Hibernate4 e TopLink5.
Uma discussão extensiva do padrão de projeto Data Access Object encontra- se fora do escopo deste material. Para um estudo mais aprofundado desse tópico, sugere-se que o leitor consulte a seguinte referência: Crupi, Malks e Alur (2004).
7.4.2 Sistema de gerenciamento de obras de arte
Esta seção apresenta uma implementação simples, baseada em alguns padrões de projeto, para o mecanismo de persistência do sistema de gerenciamento de obras de artes discutido na Seção 3.7.
Padrões de projeto. Uma das vantagens do paradigma de orientação a objetos é o seu suporte à reusabilidade, que é a prática de incorporar componentes/módulos de software já existentes em sistemas de software para os quais eles não foram originalmente desenvolvidos.
Padrões de projeto (GAMMA et al., 2000) procuram documentar conhecimentos e experiências de projetos existentes no intuito de ajudar na busca de soluções apropriadas para problemas de projeto de componentes/módulos de software.
Um padrão de projeto documenta uma alternativa de solução para um problema específico, recorrente em diversas aplicações. Ele tem uma estrutura e formato particular e descreve um problema que ocorre em um domínio em particular e como resolver esse problema.
4 http://www.hibernate.org/.
5 http://www.oracle.com/technetwork/middleware/toplink/overview/index.html.
190
O principal benefício decorrente do uso de padrões de projeto é facilitar a comunicação entre desenvolvedores de software, de uma mesma equipe ou independentes, ao permitir o emprego de estruturas de um nível de abstração maior do que linguagens de programação, porém com o mesmo grau de formalismo destas, contribuindo assim, positivamente, para a reutilização de software.
Uma descrição detalhada dos padrões de projeto existentes está além do escopo deste livro. Para mais detalhes, o leitor interessado deve consultar as seguintes referências: Gamma et al. (2000) e Crupi, Malks e Alur (2004).
7.4.2.1 Classe ConnectionFactory– Fábrica de conexões
A classe ConnectionFactory (Código 7.3) implementa o padrão de projeto Factory (GAMMA et al., 2000), que prega o encapsulamento da construção de objetos. Note que o métodogetConnection()é umafábrica de conexões. Isto é, esse método é responsável por criar e retornar novas conexões ao banco de dados (instâncias de classes que implementam a interface java.sql.Connection). O usuário dessa classe basta invocar o métodogetConnection() e terá como retorno uma conexão ao banco de dados pronta para o uso, não importando de onde ela veio e eventuais detalhes da criação.
/∗∗
∗ C l a s s e C o n n e c t i o n F a c t o r y−−Fáb r i c a de c o n e xõe s ao b a n c o de d a d o s
∗
∗ @ a u t h o r D e l a n o M e d e i r o s B e d e r
∗/
p u b l i c c l a s s C o n n e c t i o n F a c t o r y { p u b l i c C o n n e c t i o n g e t C o n n e c t i o n ( ) {
C o n n e c t i o n c o n n e c t i o n = n u l l; t r y {
S t r i n g d r i v e r = " o r g . a p a c h e . d e r b y . j d b c . C l i e n t D r i v e r " ; S t r i n g u r l = " j d b c : d e r b y : / / l o c a l h o s t : 1 5 2 7 / Museu " ; C l a s s . forName ( d r i v e r ) ;
c o n n e c t i o n = D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l , " r o o t " , " r o o t " ) ; } c a t c h ( E x c e p t i o n e ) {
e . p r i n t S t a c k T r a c e ( ) ; }
r e t u r n c o n n e c t i o n ; }
}
Código 7.3 ClasseConnectionFactory – Fábrica de conexões.
Ao encapsular dessa maneira, é possível posteriormente reimplementar o método getConnection()(o comportamento da obtenção de conexões), para, por exemplo, trocar o SGBD (de Apache Derby para MySQL) ou utilizar um mecanismo de poolingde conexões, sem ter que alterar as demais classes da aplicação.
191
7.4.2.2 Classe ObjectDTO
A classeObjectDTO(Código 7.4) implementa o padrão de projetoData Transfer Object, ou simplesmente DTO (CRUPI; MALKS; ALUR, 2004). Esse padrão de projeto é usado para transferir dados entre subsistemas de um software. Data Trans- fer Objects são frequentemente usados em conjunção com DAOs para obter e/ou armazenar dados de um banco de dados.
No caso do mecanismo de persistência do sistema de gerenciamento de obras de artes, a classe ObjectDTO torna-se a raiz da hierarquia de objetos que podem ser persistidos no banco de dados. Dessa forma, a classe ObraDeArte, que é a raiz da hierarquia de obras de artes, torna-se subclasse da classeObjectDTO.
/∗∗
∗ C l a s s e ObjectDTO−− R a i z da h i e r a r q u i a de o b j e t o s que podem s e r p e r s i s t i d o s no b a n c o de d a d o s .
∗
∗ @ a u t h o r D e l a n o M e d e i r o s B e d e r
∗/
p u b l i c a b s t r a c t c l a s s ObjectDTO {
p r i v a t e i n t i d ;
p u b l i c i n t g e t I d ( ) { r e t u r n i d ; }
p u b l i c v o i d s e t I d (i n t i d ) { t h i s. i d = i d ;
} }
p u b l i c a b s t r a c t O b r a D e A r t e e x t e n d s ObjectDTO {
/∗ D e c l a r ação de a t r i b u t o s e mét o d o s− V e r Cód i g o 3 . 6 ∗/
}
Código 7.4 ClasseObjectDTO.
7.4.2.3 Interface IGenericDAO
A interfaceIGenericDAO(Código 7.5) define as funcionalidades genéricas neces- sárias à persistência de dados. Ou seja, define os métodos genéricos que se aplicam a todos os objetos que podem ser persistidos (instâncias das subclasses deObjectDTO).
• O métodoinsert()é responsável por inserir uma instância das subclasses de ObjectDTOno banco de dados;
• O métodoselectByID()é responsável por selecionar, do banco de dados, um objeto (instância das subclasses deObjectDTO) dado o seuid;
192
/∗∗
∗ I n t e r f a c e I G e n e r i c D A O−− D e f i n e a s f u n c i o n a l i d a d e s g e nér i c a s da p e r s i s tên c i a de d a d o s .
∗
∗ @ a u t h o r D e l a n o M e d e i r o s B e d e r
∗/
p u b l i c i n t e r f a c e I G e n e r i c D A O {
v o i d i n s e r t ( ObjectDTO o b j ) t h r o w s DAOException ;
ObjectDTO s e l e c t B y I D (i n t i d ) t h r o w s DAOException ;
S e t <ObjectDTO> s e l e c t A l l ( ) t h r o w s DAOException ;
v o i d d e l e t e (i n t i d ) t h r o w s DAOException ;
v o i d u p d a t e ( ObjectDTO o b j ) t h r o w s DAOException ;
}
Código 7.5 InterfaceIGenericDAO.
• O métodoselectAll()é responsável por selecionar, do banco de dados, todos os objetos (instâncias das subclasses de ObjectDTO). Note que esse método retorna um conjunto (interfaceSet) de instâncias;
• O métododelete()é responsável por remover, do banco de dados, um objeto (instância das subclasses deObjectDTO) dado o seuid;
• E, por fim, o método update() é responsável por atualizar, no banco de dados, as informações relacionadas a um objeto (instância das subclasses de ObjectDTO).
7.4.2.4 Interface IObraDeArteDAO
A interface IObraDeArteDAO (Código 7.6) estende a interface IGenericDAO e define as funcionalidades específicas relacionadas à persistência de instâncias das subclasses deObraDeArte. Visto que a classeObraDeArte é abstrata, ela não pode ter instâncias; consequentemente, apenas instâncias de suas subclasses que podem ser persistidas em um banco de dados.
• O métodoselectAllEsculturas()é responsável por selecionar, do banco de dados, todas as esculturas (instâncias da classeEscultura);
• O método selectAllPinturas() é responsável por selecionar, do banco de dados, todas as pinturas (instâncias da classePintura).
À primeira vista, pode-se argumentar que não há justificativa para separar as fun- cionalidades relacionadas à persistência de dados em duas interfaces (IGenericDAO e
193
/∗∗
∗ I n t e r f a c e IObraDeArteDAO−− D e f i n e a s f u n c i o n a l i d a d e s e s p e cíf i c a s r e l a c i o n a d a s à p e r s i s tên c i a
∗ de i n s tân c i a s d a s s u b c l a s s e s de O b r a D e A r t e .
∗
∗ @ a u t h o r D e l a n o M e d e i r o s B e d e r
∗/
p u b l i c i n t e r f a c e IObraDeArteDAO e x t e n d s I G e n e r i c D A O {
S e t <E s c u l t u r a > s e l e c t A l l E s c u l t u r a s ( ) t h r o w s DAOException ;
S e t <P i n t u r a > s e l e c t A l l P i n t u r a s ( ) t h r o w s DAOException ;
}
Código 7.6 InterfaceIObraDeArteDAO.
IObraDeArteDAO) distintas, pois apenas obras de arte podem ser persistidas nesse sis- tema. Porém, essa separação proporciona uma maior manutenibilidade6ao mecanismo de persistência, pois facilita a sua evolução. Se futuramente for necessário adicionar uma nova entidade ao sistema (por exemplo, persistir uma nova entidade/classe), basta o desenvolvedor adicionar uma nova interface que estenda IGenericDAO, sem a necessidade de qualquer alteração nas interfaces e classes existentes.
7.4.2.5 Classe GenericJDBCDAO
A classe GenericJDBCDAO (Código 7.7) implementa parcialmente a interface IGenericDAO utilizando como estratégia para a persistência de dados o emprego da API JDBC discutida anteriormente nesta unidade.
Note que essa classe define dois métodos abstratos que devem ser implementados pelas subclassses deGenericJDBCDAO:
• O método getTableName() é responsável por retornar o nome da tabela na qual as operaçõesSQL serão executadas;
• O método createObjectDTO() é responsável por, dada uma instância da interface ResultSet (resultados da execução de uma consulta SQL), criar e retornar uma instância de alguma subclasse da classeObjectDTO.
Note que, apesar de serem abstratos, esses dois métodos são invocados nos demais métodos concretos presentes na classeGenericJDBCDAO. Ou seja, pode-se considerar cada método concreto como um Template Method – padrão de projeto Template Method(GAMMA et al., 2000).
6 Manutenibilidade, em engenharia de software, é o grau de facilidade com que um sistema de software pode ser corrigido ou aperfeiçoado (PRESSMAN, 2011).
194
/∗∗
∗ C l a s s e GenericJDBCDAO−− i m p l e m e n t a a s f u n c i o n a l i d a d e s g e nér i c a s da p e r s i s tên c i a de d a d o s .
∗
∗ @ a u t h o r D e l a n o M e d e i r o s B e d e r
∗/
p u b l i c a b s t r a c t c l a s s GenericJDBCDAO i m p l e m e n t s I G e n e r i c D A O {
p r o t e c t e d a b s t r a c t S t r i n g g e t T a b l e N a m e ( ) ;
p r o t e c t e d a b s t r a c t ObjectDTO c r e a t e O b j e c t D T O ( R e s u l t S e t r s ) t h r o w s DAOException ;
p u b l i c f i n a l S e t <ObjectDTO> s e l e c t A l l ( ) t h r o w s DAOException { S e t <ObjectDTO> s e t = new T r e e S e t <>() ;
C o n n e c t i o n c o n n e c t i o n =new C o n n e c t i o n F a c t o r y ( ) . g e t C o n n e c t i o n ( ) ; t r y {
S t r i n g s q l = "SELECT∗FROM " + t h i s. g e t T a b l e N a m e ( ) ; S t a t e m e n t s t m t = c o n n e c t i o n . c r e a t e S t a t e m e n t ( ) ; R e s u l t S e t r s = s t m t . e x e c u t e Q u e r y ( s q l ) ; w h i l e ( r s . n e x t ( ) ) {
s e t . add (t h i s. c r e a t e O b j e c t D T O ( r s ) ) ; }
s t m t . c l o s e ( ) ; c o n n . c l o s e ( ) ; // f e c h a n d o a c o n e xão } c a t c h ( S Q L E x c e p t i o n e ) {
t h r o w new DAOException ( e ) ; }
r e t u r n s e t ; }
p u b l i c f i n a l ObjectDTO s e l e c t B y I D (i n t i d ) t h r o w s DAOException { ObjectDTO d t o = n u l l;
C o n n e c t i o n c o n n =new C o n n e c t i o n F a c t o r y ( ) . g e t C o n n e c t i o n ( ) ; t r y {
S t r i n g s q l = "SELECT∗FROM " + t h i s. g e t T a b l e N a m e ( ) + " WHERE ID = " + i d ;
S t a t e m e n t s t m t = c o n n . c r e a t e S t a t e m e n t ( ) ; R e s u l t S e t r s = s t m t . e x e c u t e Q u e r y ( s q l ) ; i f ( r s . n e x t ( ) ) {
d t o = t h i s. c r e a t e O b j e c t D T O ( r s ) ; }
s t m t . c l o s e ( ) ; c o n n . c l o s e ( ) ; // f e c h a n d o a c o n e xão } c a t c h ( S Q L E x c e p t i o n e ) {
t h r o w new DAOException ( e ) ; }
r e t u r n d t o ; }
p r o t e c t e d f i n a l i n t s e l e c t L a s t I D ( ) t h r o w s DAOException { C o n n e c t i o n c o n n =new C o n n e c t i o n F a c t o r y ( ) . g e t C o n n e c t i o n ( ) ; i n t l a s t I D = 0 ;
t r y {
S t r i n g s q l = "SELECT MAX( ID ) FROM " + t h i s. g e t T a b l e N a m e ( ) ; S t a t e m e n t s t m t = c o n n . c r e a t e S t a t e m e n t ( ) ;
R e s u l t S e t r s = s t m t . e x e c u t e Q u e r y ( s q l ) ; i f ( r s . n e x t ( ) )
l a s t I D = r s . g e t I n t ( 1 ) ;
s t m t . c l o s e ( ) ; c o n n . c l o s e ( ) ; // f e c h a n d o a c o n e xão } c a t c h ( S Q L E x c e p t i o n e ) {
t h r o w new DAOException ( e ) ; }
r e t u r n l a s t I D ; }
p u b l i c f i n a l v o i d d e l e t e (i n t i d ) t h r o w s DAOException { C o n n e c t i o n c o n n =new C o n n e c t i o n F a c t o r y ( ) . g e t C o n n e c t i o n ( ) ; t r y {
S t r i n g s q l = "DELETE FROM " + t h i s. g e t T a b l e N a m e ( ) + " WHERE ID = ? " ; P r e p a r e d S t a t e m e n t s t m t = c o n n . p r e p a r e S t a t e m e n t ( s q l ) ;
s t m t . s e t I n t ( 1 , i d ) ; s t m t . e x e c u t e U p d a t e ( ) ;
s t m t . c l o s e ( ) ; c o n n . c l o s e ( ) ; // f e c h a n d o a c o n e xão } c a t c h ( S Q L E x c e p t i o n e ) {
t h r o w new DAOException ( e ) ; }
}
}
Código 7.7 ClasseGenericJDBCDAO. 195