Esse artigo faz parte da revista Java Magazine edição 30. Clique aqui para ler todos os artigos desta edição

OR: windowtext; FONT-FAMILY: Verdana">Y: Verdana; mso-bidi-font-size: 16.0pt">Conheça a nova versão do mais popular banco de dados Java

Aprenda a configurar bancos de dados HSQLDB em uma rede local ou a embutir o engine deste banco de dados em suas aplicações Java

Fernando Lozano

O HSQLDB é um banco de dados criado inteiramente em Java, capaz de operar embutido em uma aplicação ou como um servidor de rede independente. Suporta um rico dialeto SQL, incluindo triggers, integridade referencial, outer joins, visões, transações, campos BLOB, schemas, roles e consultas correlatas. O dialeto SQL do HSQLDB é mais rico do que muitos SGBDs tidos como “mais poderosos”, por exemplo o MySQL. Tudo dentro de um pacote jar contendo menos de 200 Kb (se compilado sem as ferramentas gráficas de administração e servidor web embutido).

A popularidade do HSQLDB é inegável se olharmos para os projetos que o incluem como padrão, que vão desde servidores de aplicação J2EE como o JBoss, até ferramentas de desenvolvimento desktop como o iReport. A versão 2.0 do OpenOffice, a popular suíte de escritórios que se firmou como alternativa ao Office da Microsoft, mesmo não sendo uma aplicação escrita em Java, inclui o HSQLDB como servidor de banco de dados embutido na aplicação OOo Base (que fornece funcionalidade similar ao Access da Microsoft).

O HSQLDB já foi apresentado antes nesta coluna, na Edição 7, além de ter sido usado em vários exemplos de aplicações (como nas séries recentes sobre o Tomcat 5 e o NetBeans), e em outras matérias da Java Magazine. No presente artigo são apresentados novos recursos da versão 1.8 e funcionalidades avançadas não vistas no primeiro artigo. São fornecidas também informações suficientes para quem nunca antes usou o HSQLDB decidir se ele pode ser ou não a solução para suas necessidades, e para criar as primeiras aplicações para esse banco de dados livre 100% Java.

O corpo principal deste artigo apresenta a arquitetura, características e recursos do HSQLDB. Depois são apresentadas ferramentas para administração do banco. O artigo finaliza com dicas para a programação de procedimentos armazenados. O tutorial “Primeiros passos com o HSQLDB” apresenta a instalação e o uso básico do banco de dados, incluindo a criação de uma aplicação cliente.

Terminologia e conceitos gerais

Antes de prosseguir com o HSQLDB, vamos definir a terminologia utilizada. Chamamos de banco de dados um conjunto de informações organizadas para um propósito específico. Conceitualmente, um arquivo .txt pode ser um banco de dados, por exemplo, se este arquivo for a relação de "favoritos" do seu navegador web, ou suas senhas de acesso a serviços on-line, como o de provedor internet ou um portal frequentemente visitado. Até mesmo um caderno onde se anotam telefones e endereços de e-mail dos amigos também é um banco de dados pode ser considerado um banco de dados.

Já um sistema gerenciador de bancos de dados (SGBD) é o software que gerencia o acesso a um ou mais bancos de dados, em vez de deixar outras aplicações o acessarem diretamente. O SGBD garante performance e integridade no acesso e na modificação aos dados, simplificando a escrita de aplicações. Sendo muito comum se fazer o acesso a dados por meio de SGBDs, o termo “banco de dados” é usado freqüentemente como sinônimo de SGBD.

Se o SGBD está embutido em uma aplicação, em vez de executar como um servidor de rede, costuma-se chamá-lo de engine (motor ou mecanismo) de banco de dados.

Arquitetura do HSQLDB

O HSQLDB foi criado para ser um banco de dados leve, com pouca demanda de uso de processador, memória e armazenamento. Ele é voltado para uso embarcado, seja internalizado a uma aplicação desktop, ou dentro de um hardware especialmente projetado. O HSQLDB foi, por exemplo, utilizado com sucesso no PDA Zaurus da Sharp e como parte do sistema de apuração eletrônica das eleições no Brasil (no software fornecido para a imprensa, candidatos e partidos acompanharem as apurações em tempo real).

O Projeto JVending (jvending.sf.net), uma aplicação de comércio P2P, fornece um porte do HSQLDB 1.8 para o profile CDC do J2ME. É necessário também o pacote opcional (para o J2ME) JDBC-CDC (jcp.org/en/jsr/detail?id=169). A versão customizada do HSQLDB pode ser baixada em sf.net/project/showfiles.php?group_id=10291 e o JDBC-CDC em java.sun.com/products/jdbc/download.html#cdcfp

O coração do HSQLDB é um engine SQL que opera inteiramente em memória, sem usar arquivos temporários em disco. Isto torna o HSQLDB capaz, por exemplo, de operar inteiramente a partir de um CD, ou em ambientes apenas com (pouca) memória Flash. Mas traz uma limitação: todos os registros que satisfizerem a uma consulta devem ser mantidos em memória. O mesmo ocorre com os índices das tabelas. Ou seja, embora o HSQLDB seja capaz de lidar com bancos de dados ocupando até 8 Gb em disco (utilizando o tipo de tabela cached, apresentado mais adiante), ele não será capaz de retornar todos os registros deste banco como resultado de uma única consulta.

Uma forma de contornar esta limitação é usar a cláusula LIMIT do comando SELECT, para limitar a quantidade de registros retornados, e assim transformar o que seria uma única consulta em uma sucessão de consultas que retornam, cada uma, uma fração dos resultados desejados.

O engine do HSQLDB roda como um único thread, de modo que realiza um comando SQL por vez. Se este comando for um procedimento armazenado, este será totalmente executado antes que outro comando SQL possa ser processado. Pode parecer uma limitação muito séria, mas ela permite ao engine utilizar pouca memória e para gerenciar locks e transações. De fato, o manual do HSQLDB afirma que 170 Kb de RAM são suficientes para rodar o engine (fora a quantidade de memória utilizada pelos ResultSets JDBC abertos pela aplicação e pela memória ocupada pela própria JVM).

O fato do engine utilizar um único thread não impede que o servidor HSQLDB aceite várias conexões de rede simultâneas, sendo cada uma servida pelo seu próprio thread. Também não impede que cada conexão esteja percorrendo um ResultSet diferente ao mesmo tempo, pois cada thread de conexão mantém a referência aos seus dados retornados. Mas várias conexões simultâneas aumentam a demanda de memória do servidor HSQLDB, e a execução de comandos SQL um-a-um pode comprometer o tempo de resposta quando houver uma grande quantidade de usuários simultâneos.

Por outro lado, com vários threads independentes gerenciando as conexões, as atividades que envolvem acesso a rede (envio de comandos SQL e devolução de resultados) são executadas em paralelo. Assim o HSQLDB é capaz de atender a algumas dezenas de usuários concorrentes sem que se perceba, na maioria dos casos, alguma degradação de performance.

Se uma aplicação (local ou servidora) utilizar vários bancos de dados HSQLDB simultaneamente, cada banco terá seu próprio thread de engine, de modo que usuários de um banco não competem com usuários de outras.

Benchmarks criados pelo projeto PolePosition (polepos.org) colocaram o HSQLDB de modo geral com uma performance superior a outros bancos de dados livres, entre eles o MySQL e o Apache Derby (apresentado na Edição 29). As páginas do projeto dizem que a maioria dos bancos proprietários tiveram nos testes um desempenho bastante inferior ao MySQL (e portanto também ao HSQLDB), mas questões de licenciamento impedem o projeto de divulgar os resultados para estes bancos.

Modos de operação

Para dar maior flexibilidade ao desenvolvedor, o HSQLDB pode operar em quatro modos de operação, que determinam como aplicações-clientes se comunicam com o engine SQL: Server, Standalone, Web Server e Servlet. Três desses modos de operação (Server, Web Server e Servlet) permitem o uso de conexões seguras no padrão SSL/TLS, utilizando o JCE (Java Cryptography Extensions).

Standalone

No modo Standalone, o HSQLDB roda na mesma JVM que a aplicação. Pode haver várias conexões simultâneas ao banco, desde que todas partam de outros threads na mesma JVM. Este modo é geralmente o preferido para aplicações embarcadas, por não exigir a abertura de portas TCP, nem impor o consumo de memória e processamento adicional gerado pelo envio dos comandos SQL e pela serialização dos resultados.

O engine SQL em si roda em um thread separado, que só será finalizado ao ser encerrada a JVM (chamando-se o método System.exit()) ou se for enviado o comando SQL shutdown, da mesma forma que se faria no modo Server.

Containers web ou EJB podem usar o modo Standalone em vez do modo server. Terão assim um ambiente mais leve e mais seguro, já que o banco de dados não estará exposto a conexões externas. Esta possibilidade é nova no 1.8, pois antes um banco HSQLDB no modo Standalone só permitia uma conexão por vez (veja o quadro “Novos recursos da versão 1.8”).

Server

O modo Server é o preferencial para desenvolvimento, ou quando se usa o HSQLDB como servidor de banco de dados departamental. Nesse modo de operação, são aceitas conexões em uma porta TCP (por padrão a 9001), utilizando um protocolo de aplicação próprio do HSQLDB. Dessa maneira, vários clientes em JVMs diferentes podem acessar o mesmo banco de dados simultaneamente.

O servidor só será encerrado se ele receber o comando SQL shutdown, que deve ser enviado por uma conexão realizada por um usuário com permissões de administrador do banco (por padrão o usuário "sa").

Web Server

Para situações em que se deseja fornecer acesso remoto ao banco de dados, mas há um firewall no meio do caminho, existe o modo de operação Web Server. Neste modo o HSQLDB aceita conexões TCP/IP encapsulando comandos SQL, e retorna os resultados pela mesma conexão.

Um cenário para o modo Web Server é o uso de applets Java ou do Java Web Start (JWS). Nesses casos, as configurações do sandbox[1] da JVM podem impedir que sejam criadas conexões TCP/IP a outro que não o servidor web de origem da aplicação. Assim, rodar o próprio HSQLDB como servidor web contorna esta restrições.

No modo Web Server, o HSQLDB também é capaz de responder a requisições GET e HEAD para arquivos estáticos (imagens, arquivos HTML etc.). Dessa forma, ele mesmo poderia fornecer a página web que contém o applet ou a aplicação JWS para iniciar a aplicação.

Diferentemente de conexões HTTP padrão, o HSQLDB no modo Web Server mantém a conexão aberta para receber múltiplos comandos SQL. Isso possibilita a realização de transações (o quadro “Novos recursos da versão 1.8” mostra mais detalhes).

O comando shutdown continua sendo necessário para finalizar o HSQLDB neste modo.

Servlet

O modo Servlet atende a usuários de serviços de hospedagem compartilhada em sites web. Muitos destes serviços não fornecem acesso a um banco de dados, ou fornecem apenas uma opção padrão (a mais popular é o MySQL). O usuário pode fazer a instalação de pacotes war ou em alguns casos até pacotes ejb-jar e ear, mas não pode instalar novas aplicações no servidor do provedor, especialmente aplicações que escutem em portas TCP ( pois isto pode comprometer a segurança do servidor e afetar outros usuários). Para contornar as limitações do serviço oferecido pelo provedor, o HSQLDB fornece um servlet que recebe comandos SQL como parte dos parâmetros da requisição HTTP e devolve os resultados como resposta à requisição.

O modo Servlet é praticamente igual ao Web Server – apenas o HSQLDB não responde diretamente a conexões HTTP, deixando que o container web (ou o servidor web que o contém) responda às requisições. Como no modo Web Server, ele utiliza conexões HTTP persistentes para permitir a realização de transações no banco de dados.

Da mesma forma que no modo Standalone, o engine é executado como um thread, em separado dos threads que executam o servlet do HSQLDB, e deve ser encerrado pelo comando shutdown.

Modo Standalone e servidores de aplicações

Foi dito, na descrição do modo Standalone, que esse modo pode ser adequado para aplicações web e EJB, mesmo para usuários de serviços de hospedagem compartilhada – se apenas a aplicação acessar o banco de dados. Entretanto, o modo Standalone não permite conexões remotas para realizar tarefas administrativas (como mudar as colunas de uma tabela) ou para depuração (verificar diretamente os dados armazenados em uma tabela, para conferir o resultado de uma consulta).

Por isso, alguns usuários preferem usar os modos Web Server ou Servlet – se o modo Server não foi possível por causa de firewalls ou restrições do provedor de hospedagem. Por outro lado, os modos de servidor deixam o banco exposto a conexões diretas e possíveis ataques de hackers, envolvendo captura ou adivinhação das senhas dos usuários. De modo geral, não é recomendado expor diretamente um servidor de banco de dados a conexões partindo de fora da rede local da empresa, embora o suporte a SSL no HSQLDB possa amenizar bastante os riscos.

Outros usuários usam um “console SQL” rodando como um servlet ou página JSP de uma aplicação web, que aceita comandos SQL genéricos e exibe os resultados da sua execução. Dessa forma, há a vantagem de performance do modo Standalone com a flexibilidade de realizar remotamente tarefas administrativas, sem necessidade de parar a aplicação web. Embora um console SQL como esse seja simples de escrever, deixá-lo disponível no provedor junto com a aplicação representa praticamente os mesmos riscos de segurança que deixar o próprio servidor de banco de dados aceitando conexões diretas.

Tipos de tabelas

O HSQLDB permite definir três tipos de tabelas. O tipo deve ser estabelecido no momento da criação da tabela, e determina a estrutura de armazenamento dos dados em memória e/ou em disco.

Em memória (Memory)

O tipo Memory é o padrão para a criação de tabelas. Com ele, todos os registros da tabela são mantidos em memória para acesso rápido. Entretanto, os dados são preservados permanentemente em disco na finalização do banco de dados, e também no log de transações, evitando a perda de dados em caso de falha no software ou hardware do servidor.

O uso de tabelas do tipo Memory pode levar a grandes demandas de memória na aplicação. Por outro lado, várias aplicações se beneficiam de ter seus dados inteiramente em memória, e é mais simples e confiável utilizar este recurso do HSQLDB do que usar mecanismos de cache com um banco de dados tradicional, pois o cache feito fora do banco de dados pode facilmente ficar desatualizado.

Em cache (Cached)

Tabelas Cached mantêm os registros acessados mais recentemente em memória, mas gravam todos o dados em disco de forma imediata. O tamanho do cache é configurado pelo administrador para a banco de dados como um todo, não por tabela ou por banco de dados, de modo que ele possa limitar o consumo de memória total.

Tabelas cached também ajudam a limitar o tamanho do arquivo .script do banco de dados e a duração de uma operação de checkpoint (mais sobre estes adiante).

Texto (Text)

Uma do tipo Text usa um arquivo texto comum (seguindo o padrão CSV) para armazenamento permanente dos seus registros, e a mesma área de memória para cache de registros que é utilizada para as tabelas cached. Tabelas de texto simplificam a troca de dados com fontes externas de dados, ao custo de uma pequena perda de performance.

A primeira linha do arquivo é um cabeçalho que fornece os nomes das colunas da tabela. Cada uma das linha restantes corresponde a um registro. O caractere separador de campos usado (a vírgula, como padrão), e o uso de aspas ou outro delimitador para strings podem ser definidos para cada tabela, com o comando SQL set, ou de forma global no arquivo de propriedades do banco de dados.

Definindo o tipo de uma tabela

O tipo da tabela é determinado no momento da sua criação. Entre as palavras-chave create e table deve ser indicado o tipo de tabela, e o comando SQL create table gera tabelas em memória. Dessa forma, os dois comandos a seguir são equivalentes:

create table <nome> (<colunas>...) ...

Quer ler esse conteúdo completo? Tenha acesso completo