No es un bug, es una característica no documentada

sábado, 24 de octubre de 2015

Acceso a datos. JDBC (I). Introducción

0:01 Posted by Inazio , , No comments
JDBC es un interfaz orientado a objetos de Java para SQL.
Se utiliza para enviar sentencias SQL a un sistema gestor de bases de datos (DBMS).
Con JDBC tenemos que continuar escribiendo las sentencias SQL, y ni le añade ni quita potencia al SQL.

Arquitectura JDBC

La filosofía de JDBC es proporcionar transparencia al desarrollador frente al gestor de bases de datos.

JDBC utiliza un Gestor de Controladores que hace de interfaz con el controlador específico de la BD.


JDBC en MySQL

Hay que añadir la librería mysql-connector-java-x.x.x-bin.jar a nuestro proyecto.
Por ejemplo, si compilamos desde línea de comandos, añadimos el fichero a la variable del sistema CLASSPATH, y si usamos Eclipse, vamos a Project à Properties à Java Build Path à Libraries à Add External JARs…

El driver es com.mysql.jdbc.Driver y la URL para conectar a la BD es jdbc:mysql://localhost:3306/simple

Introducción a JDBC

JDBC (Java DataBase Connectivity) es la API estándar de acceso a base de datos desde Java.
Está incluida en Java SE (Standard Edition). En Java SE 6 se incluye JDBC 4.0, pero actualmente la mayoría de bases de datos soportan JDBC 3.0.

Si se desa más información se puede visitar los siguientes enlaces

Para conectarse a una base de datos concreta, es necesario su driver JDBC.
El driver es un fichero JAR que se añade a la aplicación como cualquier otra librería (no necesita instalación adicional), y la mayoría de las bases de datos incorporan un driver JDBC.

ODBC (Open DataBase Connectivity) es un estándar de acceso a base de datos desarrollado por Microsoft. Sun ha desarrollado un driver que hace de puente entre JDBC y ODBC aunque no suele usarse.

Los pasos para que una aplicación se comunique con una base de datos son:
  • Cargar el driver necesario para comprender el protocolo que usa la base de datos concreta.
  • Establecer una conexión con la base de datos, normalmente a través de red.
  • Enviar consultas SQL y procesar el resultado
  • Liberar los recursos al terminar
  • Manejar los errores que se puedan producir

Veamos el siguiente código

import java.sql.*;

public class HolaMundoBaseDatos {

     public static void main(String[] args) throws ClassNotFoundException, SQLException {
         
          Class.forName("com.mysql.jdbc.Driver");
          Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/sample", "root", "password");
         
          Statement stmt = conn.createStatement();
          ResultSet rs = stmt.executeQuery("SELECT titulo, precio FROM Libros WHERE precio > 2");
         
          while(rs.next()){
                String name = rs.getString("titulo");
                float price = rs.getFloat("precio");
                System.out.println(name + "\t" + price);
          }
         
          rs.close();
          stmt.close();
          conn.close();
     }
}

Veamos que hace este código línea por línea:

Carga del driver

Class.forName("com.mysql.jdbc.Driver");

Antes de poder conectarse a la base de datos es necesario cargar el driver JDBC, y solo hay que hacerlo una única vez al comienzo de la aplicación.
El nombre del driver debe venir especificado en la documentación de la base de datos.

Se puede elevar la excepción ClassNotFoundException si hay un error en el nombre del driver o si el fichero .jar no está correcamente en el CLASSPATH o en el proyecto.

Establecer una conexión

Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/sample", "root", "password");

Las bases de datos actúan como servidores y las aplicaciones como clientes que se comunican a través de la red.

Un objeto Connection representa una conexión física entre el cliente y el servidor. Para crear una conexión se usa la clase DriverManager, especificando la URL, el nombre y la contraseña de nuestra base de datos.

El formato de la URL debe especificarse en el manual de la base de datos. En el ejemplo es una muestra de como conectar a MySQL. Por supuesto, el nombre de usuario y la contraseña también dependen de la base de datos.

Ejecutar una sentencia SQL

Statement stmt = conn.createStatement();
          ResultSet rs = stmt.executeQuery("SELECT titulo, precio FROM Libros WHERE precio > 2");

Una vez que tienes una conexión puedes ejecutar sentencias SQL.
Primero se crea el objeto Statement desde la conexión, y posteriormente se ejecuta la consulta y su resultado se devuelve como un ResultSet.

Acceso al conjunto de resultados

while(rs.next()){
String name = rs.getString("titulo");
float price = rs.getFloat("precio");
     System.out.println(name + "\t" + price);
}

El ResultSet es el objeto que representa el resultado.
No carga toda la información en memoria, internamente tiene un cursor en memoria que apunta a una fila concreta del resultado en la base de datos, por lo que hay que posicionar el cursor en cada fila y obtener toda la información de la misma.

El cursor puede estar en una fila concreta, y también puede estar en dos filas especiales:
  • Antes de la primera fila (Before de First Row, BFR)
  • Después de la última fila (After the Last Row, ALR)

Inicialmente el ResultSet está en BFR. next() mueve el cursor hacía delante, devolviendo true si se encuentra en una fila concreta y false si alcanza el ALR.


Cuando el ResultSet se encuentra en una fila concreta se pueden usar los métodos de acceso a las columnas
  •  String getString(String columnLabel)
  • String getString(int columnIndex)
  • int getInt(String columnLabel)
  • int getInt(int columnIndex)
  •  … (existen dos métodos por cada tipo)

Teniendo en cuenta que los índices empiezan en 1 y no en 0.

Liberar recursos

rs.close();
stmt.close();
conn.close();

Cuando se termina de usar una Connection, un Statement o un ResultSet es necesario liberar los recursos que necesitan.

Puesto que la información de un ResultSet no se carga en memoria, existen conexiones de red abiertas.

Métodos close():
  • ResultSet.close() – Libera los recursos del ResultSet. Se cierran automáticamente al cerrar el Statement que lo creó o al reejecutar el Statement.
  • Statement.close() – Libera los recursos del Statement.
  • Connection.close() – Finaliza la conexión con la base de datos.


Manejar los errores

throws ClassNotFoundException, SQLException

Hay que gestionar los errores apropiadamente, ya que se pueden producir excepciones ClassNotFoundException si no se encuentra el driver, o excepciones SQLException al interactuar con la base de datos. Por ejemplo:
  • SQL mal formado
  • Conexión de red rota
  • Problemas de integridad al insertar datos (claves duplicadas)

Lo que hacemos con la sintaxis anterior es dejar que el error lo gestionen en un nivel superior, pero si lo queremos controlar nosotros mismos, la sentencia del código quedaría tal que así:

import java.sql.*;

public class HolaMundoBaseDatos {

     public static void main(String[] args) {
         
          try{
                Class.forName("com.mysql.jdbc.Driver");
          }
          catch(ClassNotFoundException e){
                System.err.println("El driver no se encuentra");
                System.exit(-1);
          }
         
          Connection conn = null;
         
          try{
                conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/sample", "root", "password");
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT titulo, precio FROM Libros WHERE precio > 2");
               
                while(rs.next()){
                     String name = rs.getString("titulo");
                     float price = rs.getFloat("precio");
                     System.out.println(name + "\t" + price);
                }
               
                rs.close();
                stmt.close();
          }
          catch(SQLException e){
                System.err.println("Error en la base de datos" + e.getMessage());
                e.printStackTrace();
          }
          finally{
                if (conn != null){
                     try{
                          conn.close();
                     }
                     catch(SQLException e){
                          System.err.println("Error al cerrar la conexión" + e.getMessage());
                     }
                }
          }
     }
}

0 comentarios:

Publicar un comentario