Los capítulos dedicados a JDBC utilizan MySQL, sin embargo me he encontrado que en todos los sitios web especializados (nacionales y extranjeros) hay preguntas o dudas respecto a la conexión de Java con MS Access. La finalidad de este capítulo es solventar las dudas y malentendidos a este respecto, no perderemos el tiempo en la dialéctica de defensa y ataque del producto de Microsoft. Creo que es una buena base de datos de escritorio o de muy pequeños grupos, que cuando se quiere usar como base de datos departamental, algo intensiva en accesos concurrentes, empieza a convertirse en un tormento. Las razones de ello no caben en este capítulo y remito al lector a la numerosa literatura que en la web se puede encontrar sobre el tema.
Casi todas las dudas sobre JDBC y Access se refieren al manejo del puente JDBC-ODBC (controlador de nivel 1), lo que resulta lógico, ya que en general el uso de controladores nivel 3 ó 4 es menos problemático. Por tanto este capítulo se centra en el manejo de este puente.
Nuestro problema ahora es abordar la conexión JDBC con una base de datos por medio de ODBC. En la siguiente figura podemos ver diferentes tipos de acceso:
Existen controladores nativos (niveles 3 ó 4) para MS Access. Hay empresas que los ofertan, por ejemplo
http://www.jnetdirect.com o
http://www.idssoftware.com.
No es este el momento de enjuiciar estos productos. Pero en general hay un cierto consenso sobre la idea de que si
uno se esfuerza en modelos de diseño y programación Java, lo más coherente es usar bases de datos de mayor
potencia y estandarización, que ya incluyen controladores nivel 3 ó 4. Si uno va a comprar un Mercedes no quiere
que el motor sea el de un ciclomotor.
ODBC
ODBC (Open DataBase Conectivity) es el API de Microsoft para conectividad a base de datos. La idea es "antigua": dar
a los programadores un UNICO interfaz de programación (escrito en C) que permita codificar de manera independiente
al tipo de base de datos. Los que hemos trabajado directamente con el API de ODBC podemos atestiguar que resultaba
poco intuitivo y exigía muchas
líneas de código (acababas teniendo que usar una buena cantidad de handles y punteros para hacer sencillas consultas).
Por ello, proliferaron (todavía las hay) numerosas librerias que servían como interfaz de abstracción con el API de
ODBC. Afortunadamente ahora no vamos a trabajar de forma directa con ODBC, sino que accedemos al API JDBC.
Conexión JDBC-ODBC
Existen dos formas de conexión a una base de datos por medio de puente JDBC-ODBC:
Evidentemente, sea cual sea el modo de conexión necesitamos que la computadora cliente tenga instalado el
controlador ODBC. Además conviene diferenciar el controlador ODBC del origen o fuente de datos ODBC.Estos
aspectos son los que abordaremos a continuación y después hablaremos de los tipo de conexión.
¿Cómo saber que tenemos instalado el controlador ODBC?
Los archivos de configuración ODBC (ODBC.INI y ODBCINST.INI) están registrados en el sistema operativo. En la aplicación REGEDIT, que se puede ejecutar desde "Inicio-Ejecutar-regedit", puedes ver que los archivos están registrados en el sistema, concretamente en HKEY_LOCAL_MACHINE/SOFTWARE/ODBC.
¿Dónde están situados físicamente estos archivos? Se situan en el directorio de Windows (normalmente c:\windows). ODBCINST.INI es el que mas nos interesa, ya que señala los drivers (controladores) instalados en ODBC. Vamos a echarle un vistazo a ODBCINST.INI, por ejemplo con el Bloc de Notas. Si tienes instalado ODBC para MS Access tienes que ver en ODBCINST algo parecido a esto:
[Microsoft Access Driver (*.mdb) (32 bits)] Driver=C:\WINDOWS\System32\odbcjt32.dll Setup=C:\WINDOWS\System32\odbcjt32.dll 32Bit=1
Cualquier instalación normal de MS Access instala y registra su propio controlador ODBC, esto conduce a que muchos usuarios tengan instalado sin saberlo controladores ODBC de MS Access (ni falta que hace que lo sepan).
Puedes comprobar de forma cómoda que está instalado el controlador, accediendo a la aplicación del
sistema "Administrador de origenes de datos ODBC". Este es el nombre que recibe en XP. En otras
versiones recibe un nombre como "Administrador ODBC". En XP accedes a esta aplicación a través de
"Inicio - Configuración - Panel de Control - Herramientas administrativas - Origenes de datos ODBC". En
la pestaña "Controladores" puedes ver que está cargado el controlador de MS Access:
No hace falta más, esto es suficiente para una conexión directa o dinámica. Aunque la pestaña de "Data Sources"
(orígenes o fuentes de datos) este vacia, podemos hacer una conexión directa.
Origen de datos
Un origen de datos es una etiqueta (por ejemplo, "mi_quipo") que hace referencia a una base de datos, archivo .mdb en MS Access, por ejemplo "c:\doc\java\jdbc01\equipo.mdb". No nos liemos, "agregar" un origen de datos en "Administrador de origenes de datos ODBC - DSN de Archivo" (en XP) es esencialmente seguir los siguientes pasos:
Cuando usas un origen de datos ODBC haces referencia a la etiqueta, es el administrador ODBC el que
se encarga de buscar físicamente el archivo (buscarlo en la ruta que previamente has definido al
registrar el origen de datos).
Conexión directa o dinámica
Consiste en los pasos clásicos de registro del controlador puente y conexión propiamente dicha, con el prerrequisito ya comentado de tener instalado el controlador ODBC de Access. Paso por paso:
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String db = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\personal\agenda.MDB";
Connection con = DriverManager.getConnection( db, "", "");
Observa que el valor del atributo "Driver", es decir, lo que aparece entre llaves {}, debe corresponder con la entrada correspondiente en ODBCINST.INI, que aparece entre corchetes []. El segundo y tercer argumento de getConnection() es el username y password respectivamente.
No hemos necesitado definir una fuente de datos ODBC, tan sólo tener instalado el controlador ODBC de Access.
Bien, pero si no definimos una fuente de datos, entonces ¿cómo sabe mi programa Java la base de datos (.mdb) a la que tiene que conectarse? Sencillamente porque se lo hemos a indicado en la llamada a getConnection().
El controlador JDBC que sirve de puente usa la sintaxis del subprotocolo ODBC:
jdbc:odbc:<nombre_de_fuente_de_datos>[;<nombre_atributo>=<valor>]
Utilizamos el mismo controlador puente. La diferencia es que vamos a usar un origen de datos definido en el "Administrador ODBC". Si tuvieramos registrado un origen de datos ODBC cuyo nombre fuera "MiAgenda" la cosa sería:
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String db = "jdbc:odbc:MiAgenda";
Connection con = DriverManager.getConnection( db, "", "");
En muchos sitios especializados (foros, FAQs, etc.) se dice que para usar el puente JDBC-ODBC para
MS Access es necesario registrar un origen de datos en el administrador de ODBC. En el caso de Access
(y de otros productos "de escritorio") ya hemos visto que no es del todo cierto. Para una conexión directa
simplemente necesitamos que este registrado en ODBCINST.INI el controlador (driver) de MS Access.
No hace falta registrar la fuente de datos. Si trabajamos contra un servidor remoto si que resulta necesario
definir un origen de datos.
Consultas a la base de datos
En el siguiente ejemplo se produce una conexión a la base de datos 'equipo.mdb'. La base de datos tiene una tabla, denominada 'persona', con los siguientes campos:
El modo de hacer las consultas ha quedado explicado en los capítulos anteriores. El código fuente:
package jdbc01;
import java.sql.*;
import java.lang.ClassNotFoundException;
public class jdbc01_conexion_access {
public static void main(String[] args) {
try {
/*** Registro de driver y conexión a base de datos ****/
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con = DriverManager.getConnection( "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=C:/doc/java/jdbc01/equipo.MDB", "", "");
/***** Ejecutar sentencias ********/
Statement sentencia = con.createStatement();
sentencia.executeUpdate( "INSERT INTO persona (nif, nombre) VALUES ('76237006P', 'paco')");
ResultSet rs = sentencia.executeQuery( "SELECT nif, nombre, edad FROM persona" );
/*** Recorrer fila a fila el resultado ****/
while ( rs.next() ) {
String res = rs.getString("nif") +" "+ rs.getString("nombre") + ", " + rs.getInt("edad");
System.out.println( res );
}
/*** Cerramos ***/
sentencia.close();
con.close();
}
catch( ClassNotFoundException e ) { e.printStackTrace(); }
catch (SQLException e) { e.printStackTrace(); }
}
}