5.3 Criação do banco de dados
5.3.1 Conceitos sobre acesso a bancos de dados no Java
Quando se fala em acessar bancos de dados utilizando Java, é necessário conhecer três conceitos, nos quais se baseiam a conexão, a pesquisa e a utilização destes dados, otimizando os recursos disponíveis de máquina. Estes conceitos são:
• Conexão direta via Java Database Connectivity (JDBC);
• Pool de conexões;
• Camadas de persistência.
5.3.1.1 Conexão direta via JDBC
JDBC é o mecanismo básico de acesso ao banco de dados. Todos os acessos são realizados através de conexões JDBC. É uma API completa que permite realizar desde simples consultas até o gerenciamento completo do banco de dados.
Cada banco de dados tem um driver específico para acessá-lo. Este driver (normalmente desenvolvido pelo próprio fabricante do banco de dados) é específico para o banco, não havendo nenhum driver genérico.
No desenvolvimento tradicional, a cada acesso ao banco de dados é associada uma conexão. Desta maneira, se num determinado método forem executados cinco acessos ao banco, serão criadas cinco conexões. Estas conexões somente serão liberadas através de comandos no próprio programa, ou então quando o banco o banco de dados enviar um sinal de timeout. Se muitas conexões forem executadas simultaneamente (como num ambiente corporativo), o banco pode não suportar a carga, perdendo desempenho.
Criar uma conexão pode consumir vários segundos, enquanto a instrução SQL executada por ela pode consumir apenas milissegundos. Num ambiente internet, por exemplo, com milhares de usuários, o consumo de recursos seria enorme. Por esta ineficiência, a conexão via JDBC é pouco utilizada. Seu principal uso é a execução de pesquisa complexas, nas quais as camadas de persistência normalmente têm baixo desempenho.
Para resolver este problema, são utilizados os pools de conexão.
5.3.1.2 Pool de conexões
O conceito de pool de conexões é bastante simples. Ao invés de criar as conexões sob demanda, gerando sobrecarga ao banco de dados, cria-se um conjunto de conexões durante a carga da aplicação. Estas conexões vão sendo utilizadas pela aplicação. Após o uso, as conexões são
liberadas. Quando todas as conexões do pool são utilizadas, novas conexões são recusadas, ou então são adicionadas novas conexões ao conjunto já existente, aumentando sua capacidade (o comportamento depende da configuração do pool) [IMASTERS].
Não são necessárias grandes quantidade de conexões dentro do pool, pois parte-se do princípio que embora uma aplicação possa ter milhares de usuários, poucos deles farão acesso ao banco de dados num determinado momento, e o tempo utilizado para o acesso é muito pequeno (alguns milissegundos). Isto garante que sempre haja uma conexão disponível para uso.
Como as conexões não precisam mais ser criadas com grande freqüência, o desempenho do acesso ao banco de dados é muito superior, e apenas o crescimento do número de conexões é feito sob demanda. As conexões extras criadas serão canceladas pelo banco quando expirar seu timeout, não sobrecarregando nem o servidor de aplicações, nem o de banco de dados.
Um pool de conexões pode ser facilmente implementado, sendo que existem boas bibliotecas gratuitas disponíveis hoje, como o DBCP (acrônimo para Database Connection Pool), da Fundação Apache [DBCP].
5.3.1.3 Camadas de persistência
Conceitualmente, uma camada de persistência permite o armazenamento em meio físico das informações contidas num objeto.
Para uma melhor compreensão, tome-se por exemplo a tabela Projeto, criada no banco de dados Maxigroupware. Sempre que um objeto do tipo Projeto precisar ser gravado no banco de dados, deve-se obter os dados do objeto e executar um comando no banco de dados, já com os dados do projeto, para gravação.
O tratamento manual desta operação pode provocar uma grande quantidade de problemas. Por exemplo, se a estrutura da tabela for alterada no banco de dados, deve-se alterar, recompilar e redistribuir o programa para os usuários.
O objetivo da camada de persistência é abstrair o desenvolvedor deste problema.
Utilizando vários recursos do Java, ao receber um objeto do tipo Projeto, ela sabe perfeitamente quais dados obter do objeto, e a quais campos da tabela eles devem ser associados. Também gerencia um pool de conexões próprio e centraliza o acesso ao banco de dados, facilitando a manutenção do sistema.
O grande problema das camadas de persistência é que, às vezes, ela pode ser ineficiente. Sendo bibliotecas genéricas, devem trabalhar da maneira mais padronizada possível, e
portanto não pode utilizar os recursos avançados típicos de cada banco. Prendendo-se a padrões SQL, muitas vezes não seguidos pelos fornecedores de banco de dados, as camadas de persistência têm aí o seu ponto fraco.
5.3.1.4 Pool de conexões no servidor de aplicações
Como citado anteriormente, o pool de conexões otimiza bastante o acesso ao banco de dados, mas apresenta um problema. Cada aplicação deve controlar seu próprio pool. Aparentemente, esta é uma tarefa simples, mas se for levado em consideração um ambiente corporativo, pode-se chegar a alguns números interessantes. Por exemplo: um ambiente com 80 aplicações, todas acessando o mesmo banco de dados. Para cada uma delas deveria ser criado um pool com 10 conexões. Seriam utilizadas 800 conexões ao banco.
Para minimizar o problema, é possível criar um pool não na aplicação, mas no próprio servidor de aplicações, e compartilhar este pool entre várias aplicações diferentes, otimizando o acesso ao banco. No exemplo acima, poderia ser criado um único pool, com 10 conexões servindo a todas as aplicações. Deixariam de ser utilizadas 790 conexões.
Obviamente, existem limitações. A principal delas é que cada pool pode acessar apenas um banco de dados de cada vez – o que não impede que seja criado um pool para cada banco. Neste caso (e ainda utilizando o exemplo acima), num ambiente com 20 bancos diferentes, seriam criados 20 pools, totalizando 200 conexões. Ainda assim, deixariam de ser criadas 600 conexões.
5.3.1.5 Criação do pool de conexões ao banco de dados Novamente é utilizado o painel de administração do SJSAS.
• No menu principal, acesse a opção Resources / JDBC / Connection Pools;
• Na tela mostrada, clique no botão New;
• Na nova tela mostrada (ver Figura 18) informe os dados abaixo:
Name...: MaxigroupwarePool ResourceType...: javax.sql.DataSource DatabaseVendor. . : Derby
• Clique em Next;
• Na tela seguinte (ver Figura 19), preencha apenas as seguintes propriedades:
• No menu aparece o nome do novo pool conforme pode ser visto na Figura 20.
Clique sobre ele para editá-lo e exclua todas as propriedades não listadas no item anterior. Clique em Save.
Figura 18: Step 1 of 2 - Criação do pool de conexões
Figura 19: Step 2 of 2 - Propriedades do pool de conexões
Figura 20: Novo pool criado
5.3.1.6 Criação do recurso JDBC
O recurso JDBC é o elo de ligação entre a aplicação e o pool de conexões. Quando for necessário se conectar ao banco de dados, é este recurso que deve ser referenciado, o que automaticamente seleciona o pool de conexões correto.
Para criar o recurso JDBC:
• Acesse o menu Resources / JDBC / JDBC Resources (ver Figura 21 ). Depois, clique em New...;
Figura 21: Criação de um recurso JDBC
• Na tela mostrada, informe:
JNDI Name. . : jdbc/maxigroupware Pool Name...: MaxigroupwarePool
• Clique em OK;
• O recurso foi criado (ver Figura 22).
Figura 22: Recurso JDBC criado
Uma consideração sobre o JNDI Name. JNDI significa Java Naming and Directory Interface. O nome JNDI é utilizado para organizar e localizar componentes num ambiente de computação distribuído, de maneira análoga a um índice de páginas amarelas encontrado em listas telefônicas. Como conseqüência, o nome JNDI é o método mais importante de acesso aos recursos do servidor de aplicações.
Dentro do servidor de aplicações, os componentes são agrupados em categorias. Pode-se compará-las a um diretório localizado no Pode-servidor de aplicações, dentro do qual estão diversos recursos do mesmo tipo. A primeira parte do nome JNDI indica a pasta a ser pesquisada.
Por convenção, o nome do diretório com os recursos de banco de dados começa com jdbc/. Assim, para localizar o recurso JDBC chamado maxigroupware, utilizamos o endereço jdbc/maxigroupware.