Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p....

18
Revista Openacad Review, ano 3, , v.1, Rio de Janeiro – 2016 p. 44 - 60 43

Transcript of Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p....

Page 1: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3,

, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 43

Page 2: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 44

DAO – Data Access Object: Uma aplicação prática do padrão de Mapeamento Objeto Relacional Autor: Dimas Ferreira Vidal Resumo: Neste artigo se pretende apresentar o problema relacionado à persistência de objetos quando estes saem do espaço de memória em banco de dados relacional bem como soluções para o problema do mapeamento objeto relacional. Será apresentado o padrão denominado Data Access Object – DAO, fazendo uso ao mesmo tempo de alguns padrões de projeto que foram utilizados para resolver problemas que se apresentaram ao longo do processo do desenvolvimento do padrão DAO. Portanto, o que se pretende é apresentar de forma didática alguns dos fundamentos deste padrão de arquitetura de software, e ao mesmo tempo mostrar de forma prática como se pode fazer uso de padrões de projeto para sua implementação. Palavras chaves: Padrões de arquitetura, padrões de projetos, programação orientado a objetos. Abstract: This article intends to present the problem related to the persistence of objects when they leave the relational database in memory space as well as solutions to the problem of object mapping relates. Will present the standard called Data Access Object - DAO, while making use of some design patterns or have been used to solve problems that appeared throughout the DAO standard development process. Therefore, the aim is to present in a didactic way some of the basics of this software architecture standard, and at the same time show practically how one can make use of design standards for its implementation. Key words: architecture patterns, design patterns, object-oriented programming. O autor: Formado em Ciências Econômicas e em Administração, pós-graduação em Desenvolvimento de Sistemas Orientado a Objetos, e mestrado em Administração e Desenvolvimento Empresarial. Professor e pesquisador da Universidade Estácio de Sá.

1. Introdução

Uma das maiores dificuldades de quem está começando no desenvolvimento avançado em orientação a objetos é entender e aplicar na prática os principais conceitos relacionados a padrões de projeto e de padrões de arquitetura de software. Em boa parte das vezes, os exemplos de implantação de soluções que fazem uso de padrões, disponíveis na literatura, não são muito claros para os iniciados, pois em sua maioria são usados exemplos abstratos baseados em aplicações complexas, longe da realidade de quem está se aventurando neste cenário. Neste contexto, o presente artigo tem como objetivo apresentar problemas concretos de arquitetura e de projeto e possíveis soluções que podem ser implementados com o uso de padrões de arquitetura e de projetos de software.

Uma das questões que têm sido levantadas pelos desenvolvedores que se utilizam do paradigma orientado a objetos é como resolver o problema de persistência dos objetos de uma aplicação, quando estes deixam seu espaço de memória. Dentre as diversas possibilidades, o mecanismo mais maduro e amplamente utilizado é a manutenção da persistência dos atributos e em alguns casos, do estado dos objetos em um banco de dados relacional. No entanto, essa alternativa representa mais um arranjo do que uma solução propriamente dita, pois a lógica relacional não é compatível com a lógica orientado a objeto.

Para minimizar os impactos da utilização de banco de dados relacional para persistência de objetos, foram desenvolvidos padrões de arquitetura para realizar o mapeamento entre as lógicas relacional e orientação a objetos, ficando conhecidos por padrões de Mapeamento Objeto Relacional.

Ao longo deste trabalho, estaremos apresentando possíveis problemas que levaram ao desenvolvimento destes padrões, quais as soluções apresentadas, e ao mesmo tempo, como a utilização de diversos padrões de projetos permitem implementar soluções de projeto envolvidos na busca das soluções dos problemas de arquitetura. Para tanto, vamos fazer uso de estudo de caso de gestão de instâncias de objetos, representando as funcionalidades básicas de persistência necessárias a estes objetos, algumas soluções de implementação, seus impactos positivos e negativos, até que se possa

Page 3: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 45

chegar no padrão de Mapeamento Objeto Relacional que ficou conhecido como Data Access Object – DAO.

2. Padrões de Projeto e de Arquitetura de Software

Não é muito simples definir o que seja um padrão, no entanto, um padrão apresenta algumas características que podem ser utilizadas em sua identificação, dentre eles podem-se destacar:

• Um padrão surge a partir da necessidade de resolver um ou mais problemas repetitivos de projeto ou de arquitetura de software.

• Representam normalmente uma solução prática para estes problemas, e que de certa forma podem ser aplicados todas as vezes que estes problemas aparecem.

• Estas soluções podem ser utilizadas milhares de vezes, sem nunca fazê-lo da mesma maneira.

Normalmente, um padrão é bem específico a um problema de projeto ou de arquitetura de software e ao mesmo tempo, representam a essência da solução do problema e não a solução em si. Um padrão é como um gabarito que pode ser utilizado em um problema de mesma natureza, em situações e cenários diferentes (GAMMA et. al. 2008).

Segundo Gamma et. al. (2008) apud Vidal (2015), geralmente, um padrão possui quatro elementos:

a) O nome do padrão – Representa uma referencia ao padrão. Quando se pensa em uma solução a um problema de projeto ou de arquitetura, refere-se a ela pelo nome do padrão. A prática permite que a comunidade de desenvolvimento discuta possíveis soluções de problemas a partir do nome do padrão.

b) O problema – O problema descreve a condição e o contexto do problema que deve ser resolvido pelo padrão. Geralmente descreve todas as condições que devem ser satisfeitas para que seja aplicado o padrão em questão. Normalmente a descrição do padrão é complementada com um diagrama UML, geralmente um diagrama de classes relacionadas a um caso de uso, quando relacionado a projetos ou um diagrama de classes geral, quando relacionado a arquitetura.

c) A solução – Descreve o conjunto de objetos que compõem o padrão, suas interligações e seus papeis. Geralmente descreve como este conjunto de objetos resolve o problema, como um modelo genérico.

d) Consequências – Descrevem os possíveis resultados que podem ser obtidos com o padrão, os benefícios obtidos e as possíveis consequências relacionadas à dependência, a desempenho ou a uso de recursos.

2.1. Padrões de Projeto

Um padrão de projeto destina-se a resolver problemas de implementação. Geralmente estão relacionados ao paradigma Orientado a Objetos e são classificados em padrões de Criação, padrões Estruturais, e padrões Comportamentais. Os primeiros tem como finalidade a criação de objetos, os segundos com a composição das classes ou de objetos e os terceiros, como estes objetos se relacionam e distribuem seus papeis (GAMMA et. al. 2008).

Para os fins deste trabalho serão apresentados quatros padrões de projeto que foram utilizados nos exemplos do caso de uso: Factory Method, Singleton, e Iterator (GAMMA et. al. 2008).

• FACTORY METHOD – Dentre as diversas questões que devem ser tratadas por um projetista de software orientado a objetos, aquelas relacionadas com a criação de uma instância de um objeto representam parte significativa do tempo e esforço dedicados a responder as seguintes questões: quando uma instância deve ser criada, onde ela deve ser criada, quem deve ser o responsável por sua criação, qual subclasse deve ser instanciada, etc.

Page 4: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 46

Para auxiliar o desenvolvedor a responder estas quest ões foram catalogados por Gamma et. al. (2008) 5 padrões de projeto de criação de objetos, dentre os quais o Factory Method é sem sombra de dúvida o mais aplicado. Objetivo: Definir uma interface (método abstrato) para criar uma instância de objeto, ficando as subclasses decidirem que classe instanciar. A figura 1 representa o esquema lógico da implementação do padrão Factory Method.

Figura 1 – Diagrama do padrão Factory Method

Fonte: Elaboração própria

• SINGLETON – Boa parte das aplicações corporativas fazem uso intensivo de recursos, seja em número de transações, de recursos de rede, ou de número de conexões de usuários, leva o desenvolvedor a buscar um mecanismo para otimizar o uso de seus recursos computacionais. Em se tratando de orientação a objetos, em alguns casos pode ser bastante útil garantir que uma determinada classe forneça uma única instância de objeto, pois permite que o mesmo recurso possa ser compartilhado por várias transações. Objetivo – Garantir que uma classe tenha uma única instância e fornecer o acesso global a esta instância. A figura 2 apresenta um exemplo da aplicação do padrão Singleton.

Figura 2 – Exemplo do padrão Singleton

Fonte – Elaboração própria

• ITERATOR – Em uma aplicação orientado a objetos, a manipulação de uma coleção de objetos agregados leva o desenvolvedor a buscar soluções que permita acessar, listar e navegar por cada um dos objetos da coleção. Como as coleções são lugar comum na orientação a objetos, a implementação de rotinas de iteração em cada coleção fatalmente promoverá a repetição de códigos ao longo de toda aplicação. Para eliminar esta repetição é que surgiu o padrão Iterator. Neste padrão, a funcionalidade de iteração da coleção é transferida a um objeto iterator que também é um agregado da coleção (figura 3). Geralmente um objeto iterator é criado e retornado através de um método fabrica. Objetivo – Fornecer um mecanismo de manipulação de elementos de uma coleção, sem expor a sua lógica interna.

Page 5: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 47

Figura 3 – Estrutura do padrão Iterator

Fonte – Elaboração própria

2.2. Padrões de Arquitetura

Padrões de arquitetura estão relacionados a aspectos mais gerais, aos problemas de sistema, de infraestrutura ou ao uso de recursos. Dentre os diversos padrões de arquitetura, uma grande parte deles está ligada ao desenvolvimento de sistemas em camadas. O desenvolvimento de sistemas em camadas trás um número grande de vantagens quando comparado com as desvantagens, pois permite, dentre outras coisas, a divisão de um problema complexo em partes menos complexas, a separação funcional e a independência entre as diversas camadas, a substituição da funcionalidade de uma camada por outra, sem afetar as funcionalidades das outras camadas, etc (Fowler et. al.,2008).

Dentre os diversos padrões de arquitetura que fazem uso de camadas, destacam-se os padrões Cliente Servidor, o padrão de Sistemas distribuídos, o padrão MVC – Model View Control, e para os fins deste trabalho, o padrão de Mapeamento Objeto Relacioal DAO – Data Access Object.

No padrão cliente Servidor a lógica do domínio do sistema juntamente com a interface com o usuário são implementadas em uma camada separada da camada responsável pela gerência e manipulação dos dados do sistema. Geralmente estas aplicações eram desenvolvidas com o auxílio de plataformas como o Delphi e o visual Studio e banco de dados relacional. Em sistemas distribuídos a lógica de domínio é dividida e distribuída em camadas, geralmente remotas e processamento paralelo. No padrão MVC – Model View Control, como o nome sugere, são três camadas, a View fica responsável pela lógica de apresentação, ou seja pelos recursos de interface com o usuário, o Controle fica responsável pelo controle das interações dos usuários com o sistema, e a Model fica responsável pela lógica de domínio da aplicação (Silveira et. al., 2012).

O padrão DAO – Data Access Object ou em português, Objetos de Acesso a Dados tem como objetivo principal separar a camada de lógica de domínio da camada de banco de dados. Por se tratar de um padrão voltado ao paradigma orientado a objetos, permite resolver o problema, pelo menos em parte, da incompatibilidade entre a lógica da orientação a objetos e a lógica relacional dos servidores desta tecnologia. Na verdade, a motivação principal é resolver a questão de persistência dos atributos, propriedades e estado dos objetos de uma aplicação, quando estes deixam o espaço de memória através de um banco de dados relacional. Na figura 4 é apresentado um diagrama de classe com a representação do padrão (Alur, Crupi & Malks, 2005).

Figura 4 – Representação do padrão DAO – Data Access Object

Fonte – Elaboração própria

Page 6: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3,

O padrão faz uso de um objeto responsável pelo mapeamento objeto relacional, que no diagrama rde ClienteDao. Toda a lógica de manipulação dos dados do objeto com o banco de dados relacional é realizado por este objeto Dao. Funções de salvar, atualizar, deletar, e buscar dados e atributos de um objetoeste último, sendo que na função buscar, ele ainda transferência, que no gráfico recebe o nome de TransferObject

3. Uma aplicação prática e seus problemas

3.1. A classe Cliente

A figura 5 apresenta um diagrampersistência de objetos clientes.

As funcionalidades estabelecidas no diagrama de caso de uso, (casos de uso)

armazenar, recuperar, atualizar e apagar os dados dos objetos clientes em um mecanismo de persistência.diagramas abaixo representam, respectivamente, a classe cliente e a tabela Tb_cliente no banco de dados relacional.

Figura 6 –

Podemos observar que fomos obrigados a definir um atributo de identificação de persistência (idCliente) na

classe cliente para podermos acessar os atributos do relembrarmos que o identificador do objeto para a aplicação é realizado por uma posição de memória, mapeado por um ponteiro da instancia, não necessitando, portanto, de um identificador interno Ex: Cliente cliente1 = new Cliente();

Vamos implementar nossa classe cliente com sua estrutura básica:

-----------------------------------------------------------------------------------------

, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60

padrão faz uso de um objeto responsável pelo mapeamento objeto relacional, que no diagrama rde ClienteDao. Toda a lógica de manipulação dos dados do objeto com o banco de dados relacional é realizado por este

. Funções de salvar, atualizar, deletar, e buscar dados e atributos de um objeto, sendo que na função buscar, ele ainda é responsável por retornar o objeto solicitado

transferência, que no gráfico recebe o nome de TransferObject.

Uma aplicação prática e seus problemas

um diagrama de caso de uso com diversas funcionalidades necessárias à

Figura 5 – Diagrama de caso de uso

Fonte – Elaboração própria

As funcionalidades estabelecidas no diagrama de caso de uso, (casos de uso) armazenar, recuperar, atualizar e apagar os dados dos objetos clientes em um mecanismo de persistência.diagramas abaixo representam, respectivamente, a classe cliente e a tabela Tb_cliente no banco de dados relacional.

– Representação da classe cliente e de tabela cliente

Fonte – Elaboração própria

Podemos observar que fomos obrigados a definir um atributo de identificação de persistência (idCliente) na classe cliente para podermos acessar os atributos do objeto armazenados no banco de dados relacional. É importante relembrarmos que o identificador do objeto para a aplicação é realizado por uma posição de memória, mapeado por um ponteiro da instancia, não necessitando, portanto, de um identificador interno (atributo).

= new Cliente();

Vamos implementar nossa classe cliente com sua estrutura básica:

-----------------------------------------------------------------------------------------

48

padrão faz uso de um objeto responsável pelo mapeamento objeto relacional, que no diagrama recebeu o nome de ClienteDao. Toda a lógica de manipulação dos dados do objeto com o banco de dados relacional é realizado por este

fica sob responsabilidade por responsável por retornar o objeto solicitado através de um objeto de

de caso de uso com diversas funcionalidades necessárias à

As funcionalidades estabelecidas no diagrama de caso de uso, (casos de uso) são funcionalidades para armazenar, recuperar, atualizar e apagar os dados dos objetos clientes em um mecanismo de persistência. Os diagramas abaixo representam, respectivamente, a classe cliente e a tabela Tb_cliente no banco de dados relacional.

Podemos observar que fomos obrigados a definir um atributo de identificação de persistência (idCliente) na objeto armazenados no banco de dados relacional. É importante

relembrarmos que o identificador do objeto para a aplicação é realizado por uma posição de memória, mapeado por (atributo).

-----------------------------------------------------------------------------------------

Page 7: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 49

package mapeamento;

public class Cliente {

private int idCliente;

private String

nomeCliente; private

String email;

/* * --------------------------------------------- * método construtor da classe * Ao iniciarmos valores para as instancias * evitamos de ter valores null para eles. * ------------------------------------------------ */ public Cliente(){

this.idCliente = 0;

this.nomeCliente = "";

this.email = ""; }

/* Métodos de acesso aos atributos da classe. */

public int getIdCliente() {

return this.idCliente; }

public String getNomeCliente() {

return this.nomeCliente; }

public void setNomeCliente(String nomeCliente)

{ this.nomeCliente = nomeCliente; }

public String getEmail()

{ return this.email; }

public void setEmail(String email)

{ this.email = email; }

} ------------------------------------------------------------------------------------------- Abaixo o código SQL para implementar nossa tabela no MySql: -------------------------------------------------------------------------------------- # # Table structure for table 'tb_cliente' # CREATE TABLE IF NOT EXISTS tb_cliente ( id_cliente int(10) unsigned NOT NULL auto_increment, nome_cliente varchar(45) , email varchar(45) ,

PRIMARY KEY (id_cliente) ); # # Dumping data for table 'tb_cliente' # INSERT INTO tb_cliente VALUES("1", "Antonio José da Silva", "[email protected]");

INSERT INTO tb_cliente VALUES("2", "Bianca de Souza", "[email protected]"); INSERT INTO tb_cliente VALUES("3", "Bernadete de Castro", "[email protected]");

INSERT INTO tb_cliente VALUES("4", "Bruno de Magalhães", "[email protected]"); INSERT

INTO tb_cliente VALUES("5", "Dario da Fonseca", "[email protected]"); INSERT INTO

tb_cliente VALUES("6", "Sergio Ferreira", "[email protected]"); --------------------------------------------------------------------------------------

Para desenvolvermos uma aplicação que faça uso da classe cliente e realize a persistência de seus atributos no SGBD (Sistema gerenciador de Banco de dados) vamos ter que implementar os métodos responsáveis pelo mapeamento objeto relacional (cadastrar, atualizar, deletar e buscar) na classe cliente.

Para fins dos exemplos a seguir, caso tenha interesse em implementá-los, considera-se que você possua os drives do Mysql instalados e configurado.

Page 8: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 50

3.2. Implementando métodos de mapeamento objeto relacional.

Abra a classe Cliente em seu editor de preferência e insira o código abaixo. Primeiro importe a biblioteca de banco de dados. --------------------------------------------- package

mapeamento; import

java.sql.*;

public classCliente { --------------------------------------------- Agora basta implementar o método “cadastrarCliente” na classe cliente, como mostra o código abaixo: ----------------------------------------------------------------------------------------- public void cadastrarCliente(){

Connection conn = null;

Statement stm = null;

ResultSet rs = null; String StringConnection = "jdbc:mysql://localhost:3306/mapeamento"; String user = "root"; String password = ""; //------------------------------- // String Sql de INSERT // ------------------------------ String strQuery; strQuery = "insert into tb_cliente (nome_cliente,email)"; strQuery = strQuery + " values (\"" + nomeCliente + "\",\"" + email + "\")"; // --------------------------------------------------------------------------------- // No bloco try será executada a lógica para cadastrar os atributos no banco de dados

// --------------------------------------------------------------------------------------- try{

Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection(StringConnection,user,password);

stm = conn.createStatement();

stm.executeUpdate(strQuery);

System.out.println("Cliente cadastrado com

sucesso"); } catch(ClassNotFoundException e){

System.out.println("Class Excepion... Classe não encontrada"); } catch(SQLException e){

System.out.println("SQL Exception... Erro no acesso ao banco de dados"); } //---------------------------------------------------------------------- // O bloco finally será executado independente do resultado em try-catch // --------------------------------------------------------------------- finally{

try{ conn.close(); } catch(SQLException e){

System.out.println("SQLException... Erro no fechamento da conexão"); }

} }

------------------------------------------------------------------------------------------

Por último vamos criar uma aplicação cliente fazendo uso os recursos desenvolvidos, como mostra a figura 7.

Figura 7 – Diagrama de classe

Page 9: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 51

------------------------------------------------------------------------------------------ package mapeamento; public class GestaoCliente {

public static void main(String[] args) {

Cliente cliente1 = new Cliente(); cliente1.setNomeCliente("maria de jesus"); cliente1.setEmail("[email protected]"); cliente1.cadastrarCliente(); System.out.println("\n-----------------------------------------");

System.out.println("Nome do cliente: " + cliente1.getNomeCliente()); System.out.println("Eamil do cliente: " + cliente1.getEmail()); System.out.println("-----------------------------------------");

} } ------------------------------------------------------------------------------------------

A figura 8 apresenta o resultado na tela do Eclipse:

Figura 8 – tela de resultado da aplicação

3.3. Reutilização de código

Ao implementarmos as outras funcionalidades para mapeamento objeto relacional para a classe cliente, ou seja, os métodos atualizarCliente, deletarCliente e buscarCliente, teríamos que repetir a parte do código relativo às strings necessárias para executar a conexão ao banco de dados em cada método, como no exemplo abaixo: ---------------------------------------------------------------------------------------- public void

atualizarCliente(){

Connection conn =

null; Statement stm =

null; String StringConnection = "jdbc:mysql://localhost:3306/mapeamento"; String user = "root"; String password = ""; String strQuery; . . . try{

Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection(StringConnection,user,password);

. . .

. . . } ------------------------------------------------------------------------------------------

Para eliminar ou diminuir a repetição de código, vamos refatorar a classe cliente desacoplando dela as operações de conexão com banco de dados e transferindo para uma outra classe, a qual ficará responsável por esta função. Para tanto, vamos criar uma classe (MysqlConnection) responsável por estabelecer e retornar um objeto Connection (Objeto pertencente ao namespace Java.Sql).

Neste caso, vamos fazer uso de um padrão de projetos denominado Método Fábrica (Factory Method). Este método fábrica será implementado como estático para permitir que seja chamado pela classe, liberando da necessidade de criar uma instancia da classe MysqlConnection.

Como garantia de se ter uma única instância desta classe, foi utilizado o padrão Singleton, visto que se já houver uma instância de Connection, esta será retornada, no lugar de se instanciar outro objeto.

Page 10: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 52

------------------------------------------------------------------------------------------ package dbcomponente;

import java.sql.*;

public class MysqlConnection { // A classe Connection pertence ao namespace java.sql. static private Connection instance; static private String database = "mapeamento"; static private String user = "root"; static private String password = "";

private MysqlConnection(){ // Impede a criação de instancia pela diretiva new.

} public static Connection connect(){

try{ String stringConnection = "jdbc:mysql://localhost:3306/" + database; Class.forName("com.mysql.jdbc.Driver"); if (instance == null){ instance = DriverManager.getConnection(stringConnection,user,password);

} return instance;

} catch(ClassNotFoundException e) { System.out.println("excessão Classe não

encontrada"); e.printStackTrace();

} catch(SQLException e) { System.out.println("SQL Exception... Erro na conexão:"); e.printStackTrace();

} }

}

-----------------------------------------------------------------------------------------

public void cadastrarCliente(){

Connection conn =

null; Statement

stm = null;

// ---------------------------------------

// String Sql. // ---------------------------------------

String strQuery; strQuery = "insert into tb_cliente (nome_cliente,email)";

strQuery = strQuery + " values (\"" + nomeCliente + "\",\"" + email + "\")";

// -------------------------------------------------------- // Utilização do método fábrica da classe MysqlConnection // --------------------------------------------------------

conn = MysqlConnection.connect();

try{ stm =

conn.createStatement();

stm.executeUpdate(strQu

ery);

} catch(NullPointerException e) { System.out.println("SQL Exception... Objeto Statement não disponível:"); e.printStackTrace();

} catch(SQLException e) { System.out.println("SQL Exception... Erro na consulta:"); e.printStackTrace();

}finally { try{

conn.close(); }catch(SQLException e){

System.out.println("SQL Exception... Erro no fechamento:");

e.printStackTrace(); }

}

}

------------------------------------------------------------------------------------------

Page 11: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 53

Neste ponto, devemos salientar que nossa solução ainda pode ser melhorada, para tanto, vamos utilizar a classe PreparedStatement para preparar nossas strings Sql.

3.4. Trabalhando com PreparedStatement

O Java disponibiliza a classe PreparedStatement para que o desenvolvedor possa manipular de forma mais adequada e segura as strings Sql que serão executadas pelo mapeamento objeto-relacional.

A implementação abaixo substitui o mecanismo utilizado anteriormente pelo método “cadastrarCliente()” com recursos disponibilizados pela classe PreparedStatement.

----------------------------------------------------------------------------------------- public void cadastrarCliente(){

Connection conn = null; PreparedStatement stm = null; String strQuery = "INSERT INTO tb_cliente (nome_cliente,email) values (?,?)"; conn = MysqlConnection.connect();

try{

stm = conn.prepareStatement(strQuery);

stm.setString(1, nomeCliente);

stm.setString(2, email);

stm.execute();

} catch(NullPointerException e) { System.out.println("SQL Exception... Objeto Statement não disponível:"); e.printStackTrace();

} catch(SQLException e) {

System.out.println("SQL Exception... Erro na consulta:"); e.printStackTrace();

}finally { try{

conn.close(); }catch(SQLException e){

System.out.println("SQL Exception... Erro no fechamento:"); e.printStackTrace();

} }

} -----------------------------------------------------------------------------------------

Para o método buscarCliente(), são poucas as alterações necessárias para a sua implementação. A primeira será o parâmetro de identificação de registro da tabela Tb_cliente (id_cliente). Construir a instrução select necessária e atribuir os valores retornados ao objeto cliente correspondente através do objeto PreparedStatement. Por último executar a consulta e armazenar o resultado em um objeto ResultSet da biblioteca Java.Sql. ----------------------------------------------------------------------------------------- public void buscarCliente(int id){

Connection conn = null; PreparedStatement stm = null; ResultSet resultSet = null; String strQuery = "SELECT * FROM tb_cliente WHERE id_cliente = ?"; conn = MysqlConnection.connect(); try{

stm = conn.prepareStatement(strQuery); stm.setInt(1, id); resultSet = stm.executeQuery(); resultSet.first();

// ------------------------------------------------------------- // Rotina para atribuir os valores retornados do banco de dados // para os atributos do objeto. // -------------------------------------------------------------

idCliente = resultSet.getInt("id_cliente"); nomeCliente = resultSet.getString("nome_cliente"); email = resultSet.getString("email");

Page 12: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 54

} catch(NullPointerException e) {

System.out.println("SQL Exception... Objeto Statement não disponível:"); e.printStackTrace();

} catch(SQLException e) { System.out.println("SQL Exception... Erro na consulta:"); e.printStackTrace();

}finally { try{

conn.close(); }catch(SQLException e){

System.out.println("SQL Exception... Erro no fechamento:"); e.printStackTrace();

} }

} ------------------------------------------------------------------------------------------

Vamos modificar nossa aplicação GestaoCliente para podermos utilizar a funcionalidade buscarCliente. ------------------------------------------------------------------------------------------ package mapeamento;

import java.util.Scanner; public class GestaoCliente {

public static void main(String[] args) { Scanner input = new Scanner(System.in); int n = 1; do{

System.out.println("Faça sua busca digitando o código do cliente"); System.out.println("Para sair digite 0 (zero): "); n =

input.nextInt(); if

(n > 0){ Cliente cliente2 = new Cliente(); cliente2.buscarCliente(n); System.out.println("----------------------------------------------");

System.out.println("Código do cliente: " + cliente2.getIdCliente()); System.out.println("Nome do cliente: " + cliente2.getNomeCliente()); System.out.println("Emais do cliente: " + cliente2.getEmail()); System.out.println("----------------------------------------------");

} } while (n > 0);

} } ------------------------------------------------------------------------------------------

O resultado é apresentado na figura 9:

Figura 9 – tela de resultado da aplicação 3.5. O padrão Iterator e sua aplicação

Padrão Iterator (design patterns Gof Iterator) Objetivo

Fornece uma maneira de acessar sequencialmente os elementos de uma agregação de objetos sem expor sua representação subjacente.

Page 13: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 55

Outro padrão amplamente utilizado pelos frameworks e particularmente pelo Java é o padrão Iterator. Imagine duas classes que possuam um relacionamento de agregação, como apresentado no diagrama da figura 10 abaixo:

Figura 10 – Diagrama de classe

No Java, podemos mapear um relacionamento de agregação, guando a multiplicidade for de 0 ou muitos, de duas

maneiras. A primeira usando um Array e a segunda é através de uma das classes da interface Collection. A segunda opção trás algumas vantagens, dentre elas, métodos que as classes Collection disponibilizam para a manipulação dos objetos contidos na coleção. Dentre eles destacamos as funcionalidades implementadas na interface Iterator.

Para uma melhor compreensão, vamos representar esta condição em novo diagrama de classe da figura 11.

Figura 11 – Representação de Iterator no ArrayList

Um Iterador é uma classe que é desenvolvida para manipular internamente os componentes de outra classe. A vantagem de se utilizar uma classe Iterator no lugar de implementar suas funcionalidades na própria classe que a utiliza, está na reutilização de código. Vejamos no caso do Java. Seria pouco produtivo implementar o mesmo código de iteração nas diversas classes do tipo coleção disponíveis no Java. A herança também não seria muito útil, pois não traria uma maior flexibilidade para as diversas maneiras de iteração possíveis e necessárias.

A estratégia é transferir a funcionalidade de iteração para uma ou mais classes e utilizá-la como uma atividade de terceirização.

O exemplo abaixo demonstra sua aplicação pela classe ArrayList:

public String mostrarItensPedido(){ StringBuffer str=new StringBuffer();

str.append("\n---------------------------------\n"); str.append("Cliente: ------" + cliente.getNomeCliente()); str.append("\nVendedor: --------" + vendedor.getNomeVendedor()); str.append("\n---------------------------------\n");

ListIterator<ItemPedido> iterator=this.item.listIterator(); while (iterator.hasNext()){

ItemPedido itemPedido = iterator.next(); str.append("Descricao: " + itemPedido.getProduto().getDescricao()); str.append("\n"); str.append("Quantidade: " + itemPedido.getQuantidade()); str.append("\n"); str.append("Preco de venda: $R " + itemPedido.getProduto().getPreco()); str.append("\n"); str.append("Total: $R " + itemPedido.getTotal()); str.append("\n"); //str.append ("-----------------------------------

Page 14: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3,

"); str.append("\n");

this.total=this.total+itemPedido.getTotal();

} str.append("Total do pedido: $R " + this.total); return str.toString();

}

Observação importante A classe StringBuffer

O código apresentado também trás um exemplo da aplicação da classe

STRINGBUFFER do Java. Este componente disponibiliza uma maneira mais elegante

de realizar concatenação de string.

4. Implementando o padrão Data Access Object

Voltando à questão do mapeamento objeto rum objeto para um registro na tabela. cadastrarCleinte, atualizarCliente, deletarCliente e buscarCliente de

Imagine se precisássemos acessar, a partir da aplicação, uma lista três de clientes e realizar alguma

comparação entre eles. Neste caso, teríamos que implementardesejados no banco de dados e transferir os dados para cada uma das três instancias da classe cliente necessária.questão a ser colocada é: onde este método deve ser implementado?funcionalidade na classe cliente, pois é a classe que deveria ser responsável pelo acesso de seus próprios dados, mesmo que estes estejam em um outro lugar (SGDB).

Existem aplicações que se utilizam desta solução, onde um objeto cliendados e retorna o resultado em um objeto três instancia de objeto cliente, teríamos uma instancia do objeto cliente e seus dados armazenados em uma inde um objeto Dataset. Não é uma solução muito flexível, apesar de fácil implementação.

Uma solução que parece lógica é implementar o método na classe cliente (GestãoCliente). Neste caso, faríamos a consulta ao banco de dados na tabela cliente, criafaríamos a transferência dos dados da consulta para os atributos das instancias. Apesar de flexível, esta solução força a repetição das mesmas rotinas, todas as vezes que precisarmos realizar funcional

Uma solução mais sofisticada, desenvolvida pela Data Access Object - Dao, une a flexibilidade com a facilidade de implementação, além de permitir a reutilização das funcionalidades implementadas. O nome Dao é o acrônimo de Data Access Na verdade, o nome deveria ser Objeto intermediário entre o objeto e seus dados, pois é exatamente esse o propósito do padrão Dao. Se trata de um padrão de arquitetura,objetos: a camada do modelo de negócio, a camada de persistência e upelo mapeamento objeto relacional. Este padrão de arquitetura faz uso de um padrão d(Gof) para definir um objeto que sirva de intermediário entre a camada de objetos de negócio e a camada de dados, sejam elas, banco de dados relacional, arquivos XML, web

O diagrama de classe da figura

, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60

n");

this.total=this.total+itemPedido.getTotal();

str.append("Total do pedido: $R " + this.total); return str.toString();

também trás um exemplo da aplicação da classe

STRINGBUFFER do Java. Este componente disponibiliza uma maneira mais elegante

de realizar concatenação de string.

Implementando o padrão Data Access Object - Dao

Voltando à questão do mapeamento objeto relacional, vimos que foi relativamente fácil mapearmos a condição de Vamos rever o diagrama de classe de nosso primeiro exemplo, já com seus métodos

cadastrarCleinte, atualizarCliente, deletarCliente e buscarCliente definidos:

Figura 12 – Diagrama de classe inicial

Imagine se precisássemos acessar, a partir da aplicação, uma lista três de clientes e realizar alguma comparação entre eles. Neste caso, teríamos que implementar um método que pudesse realizar a busca dos registros desejados no banco de dados e transferir os dados para cada uma das três instancias da classe cliente necessária.questão a ser colocada é: onde este método deve ser implementado? Por conceito, deverífuncionalidade na classe cliente, pois é a classe que deveria ser responsável pelo acesso de seus próprios dados, mesmo que estes estejam em um outro lugar (SGDB).

Existem aplicações que se utilizam desta solução, onde um objeto cliente executa uma busca em banco de dados e retorna o resultado em um objeto Dataset, ou seja, um container de dados. Nesta solução, em vez de termos três instancia de objeto cliente, teríamos uma instancia do objeto cliente e seus dados armazenados em uma in

. Não é uma solução muito flexível, apesar de fácil implementação. Uma solução que parece lógica é implementar o método na classe cliente (GestãoCliente). Neste caso,

faríamos a consulta ao banco de dados na tabela cliente, criaríamos três instancias do objeto cliente e por último, faríamos a transferência dos dados da consulta para os atributos das instancias. Apesar de flexível, esta solução força a repetição das mesmas rotinas, todas as vezes que precisarmos realizar funcionalidades semelhantes.

Uma solução mais sofisticada, desenvolvida pela Sun Microsytem, que passou a ser conhecida por padrão Dao, une a flexibilidade com a facilidade de implementação, além de permitir a reutilização

O nome Dao é o acrônimo de Data Access Object (Objeto de acesso a Dados). Na verdade, o nome deveria ser Objeto intermediário entre o objeto e seus dados, pois é exatamente esse o propósito do padrão Dao. Se trata de um padrão de arquitetura, pois separa em três camadas o problema de persistência de objetos: a camada do modelo de negócio, a camada de persistência e uma camada intermediária que serápelo mapeamento objeto relacional. Este padrão de arquitetura faz uso de um padrão de projetos denominado Proxy (Gof) para definir um objeto que sirva de intermediário entre a camada de objetos de negócio e a camada de dados, sejam elas, banco de dados relacional, arquivos XML, web Services, dentre outras.

da figura 13 abaixo apresenta uma visão do padrão Dao:

56

também trás um exemplo da aplicação da classe

STRINGBUFFER do Java. Este componente disponibiliza uma maneira mais elegante

elacional, vimos que foi relativamente fácil mapearmos a condição de Vamos rever o diagrama de classe de nosso primeiro exemplo, já com seus métodos

Imagine se precisássemos acessar, a partir da aplicação, uma lista três de clientes e realizar alguma um método que pudesse realizar a busca dos registros

desejados no banco de dados e transferir os dados para cada uma das três instancias da classe cliente necessária. A Por conceito, deveríamos implementar esta

funcionalidade na classe cliente, pois é a classe que deveria ser responsável pelo acesso de seus próprios dados,

te executa uma busca em banco de , ou seja, um container de dados. Nesta solução, em vez de termos

três instancia de objeto cliente, teríamos uma instancia do objeto cliente e seus dados armazenados em uma instancia

Uma solução que parece lógica é implementar o método na classe cliente (GestãoCliente). Neste caso, ríamos três instancias do objeto cliente e por último,

faríamos a transferência dos dados da consulta para os atributos das instancias. Apesar de flexível, esta solução força idades semelhantes.

, que passou a ser conhecida por padrão Dao, une a flexibilidade com a facilidade de implementação, além de permitir a reutilização

(Objeto de acesso a Dados). Na verdade, o nome deveria ser Objeto intermediário entre o objeto e seus dados, pois é exatamente esse o propósito

pois separa em três camadas o problema de persistência de ma camada intermediária que será responsável

e projetos denominado Proxy (Gof) para definir um objeto que sirva de intermediário entre a camada de objetos de negócio e a camada de dados,

Page 15: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 57

Figura 13 - Representação do padrão Dao

Para melhor entendermos o processo utilizado pelo padrão Dao, vamos analisar três serviços diferentes a

partir da classe Dao: Cadastrar, Buscar e Listar. Fluxo para o serviço de cadastrar cliente será: Levar o objeto Cliente da aplicação para a persistência

(DataSource).

Figura 14 – Fluxo de serviço da classe Dao

Para os serviços buscar cliente e listar clientes, o fluxo será o inverso, ou seja, o objeto Dao trará o objeto Cliente da fonte de dados para a aplicação, como mostram as figuras 14 e 15. A diferença básica será que no serviço de buscar cliente, o objeto Dao retornará um único objeto Cliente e para o serviço de Listar clientes, são retornados vários objetos clientes.

Figura 15 – Fluxo de serviço buscar cliente da classe Dao

4.1. Metodologia para implementação do padrão Dao

Primeiramente implementamos a classe cliente com atributos e métodos de acesso aos atributos. Em seguida, implementamos na classe ClienteDao os métodos de acesso e manipulação de persistência dos atributos no banco de dados relacional.

Desenvolvemos as estratégias de transferência dos objetos da camada de negócio para as duas direções.

Page 16: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 58

Vamos exemplificar o uso do padrão Dao na aplicação do exemplo anterior. Código da classe cliente: -----------------------------------------------------------------------------------------------------

-

package mapeamento; public class Cliente {

private int idCliente;

private String

nomeCliente; private

String email;

/* * ------------------------------------------------ * método construtor da classe * Ao iniciarmos valores para as instancias * evitamos de ter valores null para eles. * ------------------------------------------------ */

public Cliente(){

idCliente = 0;

nomeCliente = "";

email = ""; }

/* * Métodos de acesso aos atributos da classe. */

public int getIdCliente() { return idCliente;

} public void setIdCliente(int

idCliente) { this.idCliente = idCliente;

} public String

getNomeCliente() { return nomeCliente;

}

public void setNomeCliente(String nomeCliente) { this.nomeCliente = nomeCliente;

}

public String getEmail() { return email;

}

public void setEmail(String email) { this.email = email;

}

}

---------------------------------------------------------------------------------------------------- Código da classe ClienteDao ----------------------------------------------------------------------------------------------------

package

mapeamento;

import

java.sql.*; import dbcomponente.MysqlConnection; public class ClienteDao{ /*------------------------------------------------------------------------------

No método cadastrarCliente passamos uma instancia da classe Cliente para Dentro da classe ClienteDao para que esta possa persisti-lo ------------------------------------------------------------------------------ */

Page 17: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 59

public void cadastrarCliente(Cliente cliente){

Connection conn = null; PreparedStatement stm = null; String strQuery = "INSERT INTO tb_cliente (nome_cliente,email) values (?,?)"; conn = MysqlConnection.connect(); try{

stm = conn.prepareStatement(strQuery); stm.setString(1, cliente.getNomeCliente()); stm.setString(2, cliente.getEmail()); stm.execute(); System.out.println("---------------------------------------"); System.out.println("atributos de objeto salvo com sucesso"); System.out.println("---------------------------------------\n");

} catch(NullPointerException e) { System.out.println("SQL Exception... Objeto Statement não disponível:"); e.printStackTrace();

} catch(SQLException e) {

System.out.println("SQL Exception... Erro na consulta:"); e.printStackTrace();

}finally { try{

conn.close(); } catch(SQLException e){

System.out.println("SQL Exception... Erro no fechamento:"); e.printStackTrace();

} }

} -----------------------------------------------------------------------------

No método buscarCliente a operação se inverte, ou seja, o objeto clienteDao retornará uma instancia da Classe Cliente a partir dos atributos no banco de dados. ----------------------------------------------------------------------------- public Cliente buscarCliente(int id){

Cliente cliente = null; Connection conn = null; PreparedStatement stm = null; ResultSet resultSet = null;

String strQuery = "SELECT * FROM tb_cliente WHERE id_cliente = ?"; conn = MysqlConnection.connect();

try{

stm = conn.prepareStatement(strQuery); stm.setInt(1, id); resultSet = stm.executeQuery(); resultSet.first(); cliente = new Cliente(); cliente.setIdCliente(resultSet.getInt("id_cliente"));

cliente.setNomeCliente(resultSet.getString("nome_cliente"));

cliente.setEmail(resultSet.getString("email")) ;

return cliente;

} catch(NullPointerException e) { System.out.println("SQL Exception... Objeto Statement não disponível:"); e.printStackTrace();

} catch(SQLException e) {

System.out.println("SQL Exception... Erro na consulta:"); e.printStackTrace();

}finally { try{ conn.close(); }catch(SQLException

e){ System.out.println("SQL Exception... Erro no fechamento:"); e.printStackTrace();

} }

}

Page 18: Revista Openaca Review, ano 3, , ano 3, v.1, Rio Janeiro – 2016 p. …openacad.com.br/~openacad/files/Artigos/OpenAcadReview... · 2016-11-28 · Revista Openaca Review, ano 3,

Revista Openacad Review, ano 3, v.1, Rio de Janeiro – 2016 p. 44 - 60 60

5. Conclusão

O principal objetivo deste artigo foi apresentar de forma didática, Alguns padrões de projeto, bem como alguns fundamentos de arquitetura para mapeamento objeto-relacional, sem, no entanto, fechar questão tão complexa.

Ao apresentar exemplos de implementação, a opção foi pela simplificação didática. Portanto, o leitor deve levar este fato em consideração se for usá-los em alguma aplicação prática.

Outros artigos apresentando outros padrões de arquitetura e de projetos estarão disponíveis em breve. Sugerimos inclusive que outros autores também pudessem fazê-lo, tal que disponibilizássemos para a comunidade um material teórico em português mais vasto sobre um tema tão complexo.

6. Bibliografia

BRAUDE, Eric, Projeto de Software, Bookman, São Paulo, 2005.

CADENHEAD, Roger; LEMAY, Laura, Java2 – aprenda em 21 dias, rio de Janeiro, Campus, 2005.

DALL’OGLIO, Pablo, PHP Programação com Orientação a Objetos. Novatec, São Paulo, 2007. FOWLER, Martim at all, Padrões de Arquitetura de Aplicações Corporativas, Bookman, São Paulo, 2006. GAMMA, Erich, at all, Padrões de Projeto, São Paulo, Bookman, 2000. GUTMANS, A, PHP 5 – Programação Poderosa. Alta Book, Rio de Janeiro, 2005. HORSTMANN, Cay, Padrões e Projeto Orientados a Objetos, São Paulo, Bookman, 2007. SINTES, Anthony, Aprenda Programação Orientado a Objetos em 21 dias, Makron Books, São Paulo, 2002.

SOARES, Walace, PHP 5 Conceitos, Programação e Integração com Banco de Dados. Editora Érica, São Paulo, 2004.