JDBC: Maldito Access: como resolver o problema “não é possível abrir mais tabelas (can’t open more tables)”

Então aconteceu com você: um belo dia teve de programar em Java acessando o maldito “banco de dados” Access… Seu código está escrito corretamente e a aplicação é iniciada. No início, tudo vai bem, você até se surpreeende com o fato de estar funcionando, até que, sem mais nem menos, começam a surgir excessões com as mensagens “Não é possível abrir mais tabelas” ou, em inglês: “can’t open more tables”.

É um daqueles momentos nos quais você realmente pensa em matar o infeliz que optou por usar este “banco de dados”. Mesmo consultas que só envolvam uma tabela começam a disparar esta excessão e, mesmo que você feche todas as suas instâncias das classes ResultSet e PreparedStatement, ou mesmo suas conexões com o banco, o erro persiste.

A impressão que temos é que só é possível trabalhar com este (argh) “banco de dados” se estivermos programando em VB ou VBA. Na prática, esta é a realidade, e,  como irei mostrar a seguir, a solução para este problema não poderia ser mais tosca. Todo o problema está no driver de acesso ODBC ao Access.

Este driver, desenvolvido pela Microsoft (lógico) suporte apenas 1024 consultas a um banco Access. Sendo assim, você precisa fechar todas as consultas ou statements que venha a executar com relação a este banco. O mais interessante é: não basta chamar o método close() das classes ResultSet e PreparedStatment e, para minha surpresa, também não é necessário ficar criando e fechando sucessivas conexões com o “banco” Access.

Basta seguir o seguinte procedimento:

  1. Conecte-se ao “banco”. Você poderá reaproveitar sua conexão com o arquivo do Access. O problema não é com ela (bônus para você, pois não precisará mais sacrificar sua performance abrindo e fechando conexões a cada consulta).
  2. Instancie o seu objeto ResultSet ou PreparedStatement, e em seguida faça o que tem de fazer.
  3. Finalizada a execução, chame o método close da sua classe.
  4. Como se não bastasse chamar o método close(), defina a sua instância do objeto como null.

De tempos em tempos (vamos supor, de 20 em 20 execuções, por exemplo) chame o garbage colector do Java para limpar as variáveis não utilizadas. Pasme: somente assim as consultas são fechadas com o “banco e dados” em questão.

É uma gambiarra? Com certeza. A performance vai ser prejudicada? Pode apostar. É uma solução elegante? Nem um pouco. Mas por outro lado, você está usando uma das piores opções que existem. Só o fato de estar usando Access já é uma gambiarra, sendo assim, infelizmente, sofra as consequências.

Descobri esta solução enquanto desenvolvia uma “aplicação” que precisava do Access (no meu caso, o 97) no Netbeans. Ao executá-la no ambiente da IDE, o erro não aparecia. Ao executá-la independentemente, o erro aparecia (e sempre). Constatei então que o Netbeans chama o garbage colector constantemente, ao passo que minha aplicação não. Visto que já sabia do bug do driver, somei 2 + 2 e resolvi tentar esta solução. Para minha surpresa, funcionou melhor que o esperado. A perda de performance não foi tão grande e, para minha surpresa, a excessão simplesmente desapareceu.

Tudo bem: o principal problema com o Access foi resolvido. No entanto, faça um favor a você e aos futuros programadores que, por desventura venham a dar manutenção em seus sistemas: ESQUEÇA O ACCESS!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>