Do que se trata o artigo
O artigo aborda a criação passo a passo de uma pequena aplicação GUI com acesso a banco de dados. Nesta primeira parte são criadas as classes do domínio da aplicação e as classes necessárias para a persistência.

Em que situação o tema é útil
O tema abordado é fundamental para quem precisa criar aplicações com GUI e que implementam acesso a banco de dados. Além disso, é útil para o desenvolvimento em camadas, que neste caso é a interface com o usuário, as classes do domínio de negócio e a camada de persistência.

Desenvolvendo uma aplicação passo a passo
A maneira de abordar a solução de um problema de desenvolvimento se inicia com o entendimento da questão, passando pela criação do modelo do domínio do problema e do diagrama de classes. Nessa etapa, um dos passos, caso a aplicação necessite implementar persistência, consiste em fazer o mapeamento objeto-relacional. Após isso, finalmente inicia-se a codificação, que é a última etapa do processo, antes de efetuar os testes junto com o usuário. Assim, nesta primeira parte da série de artigos buscamos apresentar um problema, cuja solução segue esses passos.

Na Easy Java Magazine nº 4 foi proposta pelo autor uma metodologia simples para resolver problemas de programação, no artigo “Solucionando Problemas usando Java”. Na matéria que ora iniciamos será apresentada uma aplicação mais complexa que os exemplos usados no artigo citado, que demanda uma metodologia mais adequada à sua solução. No entanto, em linhas gerais, o processo é similar e tentaremos acompanha-lo, visto que foge do escopo deste artigo a utilização de processos estudados na Engenharia de Software.

Na implementação do programa optou-se por criar uma interface gráfica utilizando a API Swing, à qual já foi dedicado o artigo “Swing: O Desktop Java” na Esay Java Magazine nº 12. Com o objetivo de facilitar a criação das telas será empregado o plug-in WindowBuilder, disponível para o Eclipse. Entretanto, se o leitor tiver habilidade com o NetBeans, este também poderá ser usado. É importante observar que ambas as tecnologias já foram objeto de matérias também nesta revista.

A camada de persistência foi desenvolvida usando uma solução apresentada na Edição nº 4 da Easy Java, no artigo “Solucionando problemas usando Java”. Poderíamos ter optado por usar o padrão DAO (Data Access Object) ou um framework tal como Hibernate, mas isso traria uma complexidade maior ao desenvolvimento. Todavia, a solução adotada ainda consegue uma separação entre as camadas de persistência, regras de negócio e interface gráfica.

Seguindo esta linha, inicialmente será apresentado o problema. Depois disso será iniciado o processo de solução, começando com a análise do problema. Após a análise, o problema será dividido em partes que possam ser solucionadas individualmente e depois integradas na solução final. Em seguida será implementada cada uma das partes nas quais o problema foi separado.

Nesta primeira parte da matéria serão criadas as classes do domínio do problema e as classes necessárias para implementar a persistência.

Definição do Problema

É um fato corriqueiro que pessoas que possuem uma biblioteca particular emprestem livros aos amigos. E infelizmente é bastante comum que os amigos dificilmente devolvam as obras, e as pessoas terminam mesmo por esquecer a quem foram emprestadas. Pensando nisso, o autor propõe o desenvolvimento de um pequeno aplicativo que registre as obras mantidas em uma biblioteca pessoal. E, para evitar o esquecimento, que os dados dos empréstimos sejam também registrados.

Análise do Problema

O primeiro passo na análise é identificar o domínio do problema, que consiste em definir as classes e seus relacionamentos. A partir da descrição do problema, pode-se inferir que existem as entidades Livro e Emprestimo. Sabendo-se que um Livro possui pelo menos um autor, determinaremos também como parte do domínio, a entidade Autor. Quanto aos relacionamentos, pode-se afirmar que um livro tem um ou mais autores e um autor pode escrever mais de um livro. Define-se também que um livro pode ser emprestado mais de uma vez. Dessa maneira criamos um modelo do domínio, mostrado na Figura 1.

Utilizamos a UML (Unified Modeling Language) para criar o diagrama de classes que irá representar o modelo do domínio do problema. Assim, conforme a Figura 1, foram representadas as classes, seus relacionamentos e multiplicidades. Note que a multiplicidade do relacionamento entre Autor e Livro determina que um autor pode ter um ou mais livros publicados e um livro deve ter pelo menos um autor. Um livro pode ter um ou muitos empréstimos e um empréstimo é feito para um único livro.

O passo seguinte consiste em definir os dados relevantes a cada uma das classes identificadas. Na classe Autor, por exemplo, consideramos como importante o nome do mesmo. Na classe Livro, identificamos os campos isbn (um número identificador único para livros), titulo, ano de edição, edição e editora. Nome do emprestador, data do empréstimo e data da devolução são dados importantes a serem registrados na classe Emprestimo.

Na etapa seguinte do processo será apresentada uma possível solução. É o que podemos chamar de um projeto.

Solução Proposta

Antes de projetar a solução do problema deve-se pensar na persistência dos dados, e uma alternativa muito utilizada pelos desenvolvedores é o padrão DAO (Data Access Object). DAO é um padrão de persistência que permite separar as regras de negócio das regras de acesso ao banco de dados. Ele funciona tanto para pegar os objetos Java, e enviá-los ao banco de dados usando comandos SQL, quanto para buscar os dados do banco e convertê-los em objetos que possam ser tratados pela aplicação.

Para se conseguir implementar esse padrão, uma das tarefas do processo é mapear as classes para entidades do modelo relacional. Mas falaremos sobre isso com mais detalhes em seguida. Por ora apenas consideramos necessário fazer uma modificação no modelo do domínio, para que o mapeamento seja feito adequadamente. A modificação consiste em mudar o relacionamento entre Autor e Livro para agregação, e adicionar um atributo do tipo Set para receber os autores na classe Livro. Essa modificação visa facilitar a implementação da solução, pois um relacionamento muitos-para-muitos requer a criação de uma entidade associativa no banco de dados, para representar o relacionamento. Dessa forma, quando salvarmos os dados de um Livro, a classe persistente se encarregará também de salvar os autores na tabela associativa. Isso ficará mais claro quando forem apresentadas as implementações das classes persistentes. Na Figura 2 mostramos esse novo modelo, já incluídos os atributos.

Modelo do domínio do problema

Figura 1. Modelo do domínio do problema.

Diagrama de classes do domínio do
problema

Figura 2. Diagrama de classes do domínio do problema.

Observe que, além dos atributos identificados anteriormente, foi definido na classe Livro o campo situacao, responsável para indicar se um livro está emprestado ou não. Será considerado o seguinte: se o livro estiver emprestado, situacao terá o valor 2, caso contrário, assumirá o valor 1.

Agora que já se tem um modelo de classes, podemos definir como será o modelo ER (Entidade Relacionamento) correspondente ao mapeamento objeto-relacional.

Para obter esse novo modelo, precisamos rever algumas estratégias do mapeamento objeto-relacional, de uma perspectiva bastante simples, voltada para a solução do nosso problema atual:

· Um atributo de uma classe pode ser mapeado para zero ou mais colunas em um banco de dados relacional. O mais comum é o mapeamento um-para-um, no entanto, podem-se citar dois extremos. Um caso é quando se tem um atributo de classe que não é persistente, tal como a média de compras da classe Cliente. Visto que esse campo pode ser calculado, então não precisa ser salvo no banco de dados. O outro extremo é quando um atributo é um objeto, tal como Endereco na classe Cliente. Isso levaria a uma associação entre duas classes e consequentemente seria necessário mapear os atributos de Endereco;

· Em geral cada classe é mapeada para uma tabela. No entanto existem casos em que isso não acontece, tal como nos relacionamentos de generalização/especialização, que não estudaremos neste artigo;

· Nos relacionamentos um-para-muitos, o mapeamento é feito definindo-se uma chave estrangeira na tabela muitos. Na situação do problema ora exposto, as classes Livro e Emprestimo são um exemplo disso. Dessa forma, no modelo relacional, a tabela Emprestimo terá uma chave estrangeira referenciando a tabela Livro;

· Nos relacionamentos muitos-para-muitos é necessário o conceito de uma tabela associativa, cuja finalidade é manter o relacionamento entre duas ou mais tabelas. Este é o caso do relacionamento Livro-Autor. Para mapear esse relacionamento será criada a tabela AutorLivro, que terá chaves estrangeiras referenciando Autor e Livro.

Após essas considerações pode-se então apresentar o modelo ER, mostrado na Figura 3, derivado do diagrama de classes da Figura 2.

Diagrama ER produzido a partir do
mapeamento objeto-relacional

abrir imagem em nova janela

Figura 3. Diagrama ER produzido a partir do mapeamento objeto-relacional

Pode-se observar na Figura 3 que foram definidas chaves primárias para as entidades, pois essa também é uma tarefa do mapeamento objeto-relacional. Nesse exemplo, preferimos escolher números sequenciais – sem significado nas regras do negócio – para as chaves. A outra alternativa é escolher chaves naturais – atributos que fazem parte do objeto – tal como isbn da classe Livro. Um artigo, citado nos links, discute essa questão de escolher a chave primária das entidades.

O passo seguinte no projeto corresponde a definir as classes necessárias para implementar a persistência na aplicação. Uma solução muito utilizada é o padrão DAO (Data Access Object). DAO implementa o encapsulamento e a centralização do acesso a fontes de dados – banco de dados, arquivos texto, XML, entre outros. Tal implementação permite que se separe a lógica de negócio da persistência. A camada de lógica de negócio consiste das classes do sistema, que no presente exemplo correspondem a Autor, Livro e Emprestimo. Já a camada de persistência se refere às classes responsáveis pelo acesso às fontes de dados.

No entanto, deixaremos essa solução para outra matéria em virtude da sua complexidade, posto que isso nos forçaria a expor toda a sua teoria antes de apresentar a solução. Por ora, então, será utilizada uma proposta apresentada no artigo “Solucionando problemas usando Java”, publicado na Easy Java Magazine nº 4.

Na solução que foi apresentada nesse artigo foram criadas a classe Conexao, responsável por fazer a conexão com o banco de dados, e uma classe persistente para cada tabela no diagrama ER. Com isso chegou-se ao diagrama de classes persistentes mostrado na Figura 4.

Veja nesta figura que foi definida uma interface denominada GenericDB, a qual servirá para determinar os métodos que deverão ser obrigatoriamente implementados pelas classes AutorDB, LivroDB e EmprestimoDB. O leitor deve ter notado que não criamos uma classe correspondente à entidade AutorLivro – que foi utilizada para implementar o relacionamento muitos-para-muitos entre Livro e Autor. Esta decisão foi tomada porque a gravação/alteração dos dados na tabela AutorLivro será feita através dos métodos correspondentes da classe LivroDB.

Para concluir esta fase, definiremos que a interface com o usuário será construída usando Swing e o banco de dados será o Apache Derby. A opção pelo Derby se deve ao fato de que esta é uma aplicação simples e de uso pessoal, não exigindo maiores recursos, e que pode ser implementada utilizando um banco de dados embutido.

Diagrama de classes persistentes

abrir imagem em nova janela

Figura 4. Diagrama de classes persistentes.

Codificação da Solução

Antes de começar a implementação é necessário preparar o ambiente, que consiste fundamentalmente em obter o driver JDBC para o Apache Derby e depois configurá-lo no IDE que será utilizado – que neste caso será o Eclipse. Se o leitor estiver acompanhando o desenvolvimento, é importante destacar que qualquer banco de dados pode ser usado em substituição ao Derby, desde que você obtenha o driver JDBC correspondente.

Acesse o endereço do Apache Derby que consta na relação de links, baixe o pacote do banco de dados e instale-o no diretório de sua preferência.

Em seguida crie um projeto Java no Eclipse, denominando-o BibliotecaPessoal, por exemplo. Após o projeto ter sido criado, precisamos adicionar a biblioteca do banco de dados. Para isso, com o projeto selecionado, pressione ALT + ENTER. Essa ação irá abrir a janela de Propriedades do Projeto, de acordo como mostra a Figura 5.

Nessa janela, selecione na caixa do lado esquerdo o item Java Build Path e, logo após, escolha a aba Libraries. Feito isso, clique no botão Add External JARs. Localize então o arquivo Derby.jar sob a pasta lib localizada no diretório onde a biblioteca do banco de dados foi instalada. Por fim, pressione o botão Abrir e depois o botão OK para confirmar a inclusão da biblioteca.

Concluída esta parte podemos partir para o desenvolvimento propriamente dito. Inicialmente vamos dividir nosso projeto em três pacotes: br.com.biblioteca.dominio, br.com.biblioteca.persistencia e br.com.biblioteca.ui. Portanto, crie esses três pacotes no menu de contexto do projeto. Para fazer isso, pressione o botão direito do mouse sobre o nome do projeto e selecione ...

Quer ler esse conteúdo completo? Tenha acesso completo