Para poder conectar una aplicación Java con base de datos lo primero que hay que tener en cuenta es el motor que se maneja, ya que de esto dependerá el conector que debemos integrar en la aplicación entre los que encontramos MySQL, PostGreSQL, etc… El driver de conexión de MySQL lo podemos encontrar en su página oficial . Con el archivo .jar descargado tan solo queda integrarlo como librería externa del proyecto para que se puedan utilizar las clases de sql necesarias para trabajar con los datos. Para ello en el menu de Proyect Structure –> Dependencies — Libraries y agregar el .jar descargado

Una vez hecho esto el proyecto está preparado para utilizar las bases de datos mysql.

Establecer la conexión

Para establecer la conexión con la base de datos se ejecuta la URL con los parámetros integrados en formato jdbc para poder abrir el canal de comunicación. Esta URL pasada como parámetro al método getConnection dela clase DriverManager obtendrá un objeto de tipo Connection mediante el cual se podrá utilizar la base de datos

Connection con = null;
String host = "127.0.0.1";
String user = "root";
String pass = "";
String dtbs = "nombre_db";
String newConnectionURL = "jdbc:mysql://" + host + "/" + dtbs
                    + "?" + "user=" + user + "&password=" + pass;
conn = (java.sql.Connection) DriverManager.getConnection(newConnectionURL);

Esta parte del código además tendrá una excepción de tipo SQLException por si ocurre cualquier error en la conexión (nombre, pass, etc…). Una vez la conexión está creada se pueden ejecutar los métodos para el tratamiento de datos. Lo normal es crear una clase externa donde se gestiona la conexión, abriéndola, obteniéndola cuando es necesario y cerrándola cuando no se utiliza.

public class Conexion {

    java.sql.Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    String host = "127.0.0.1";
    String user = "root";
    String pass = "";
    String dtbs = "nombre_db";

    public Boolean realizarConexion(){

        try
        {
            Class.forName("com.mysql.jdbc.Driver");
            String newConnectionURL = "jdbc:mysql://" + host + "/" + dtbs
                    + "?" + "user=" + user + "&password=" + pass;
            conn = (java.sql.Connection) DriverManager.getConnection(newConnectionURL);
            return true;
        }
        catch(SQLException ex)
        {
            System.out.println("Error la Base de Datos");
            ex.printStackTrace();
            return false;
        }
    }

    public java.sql.Connection getConnection(){
        return conn;
    }

    public void cerrarConexion(){
        conn = null;
    }
}

En este ejemplo se trabaja con MySql pero si se conecta con otro tipo de motor la sintaxis sería:

// MySQL
Connection conexion = DriverManager.getConnection(
   "jdbc:mysql://servidor:3306/database",
   "usuario",
   "password"); 
// Oracle 
Connection conexion = DriverManager.getConnection(
   "jdbc:oracle:thin:@servidor:1521:database",
   "usuario",
   "password");  
// Access
Connection conexion = DriverManager.getConnection(
   "jdbc:odbc:nombre_fuente_datos");
// PostgreSQL
Connection conexion = DriverManager.getConnection(
   "jdbc:postgresql://servidor:5432/database",
   "usuario",
   "password");

Administrar los datos

Una vez está creada la conexión tan solo hace falta obtener el objeto que posibilita trabajar con ellos. Para esto tendremos disponibles los objetos:

  • Statement: con el cual podremos ejecutar una sentencia SQL mediante sintaxis propia de MySQL
  • PrepareStatement: con el cual podremos ejecutar una sentencia mediante la preparación de argumentos.
  • Resultset: con el cual obtendremos los resultados de una query.

Statement

Permite ejecutar querys escritas en sql de forma sencilla mediante la ejecución del métodos. Para poder crear un objeto de tipo Statement previamente debe existir un objeto de tipo connection disponible creado en el ejemplo anterior:

Statement c = (Statement) conn.createStatement();

Una vez se tiene el objeto statement se pueden ejecutar los siguientes métodos:

  • executeUpdate(): para poder ejecutar querys SQL que tengan como resultados registro de modificación de la estructura de tablas de la base de datos. Normalmente se suelen asociar a querys de formato INSERT, DELETE, UPDATE
  • executeQuery(): para poder ejecutar querys SQL que tengan como resultado registros. Normalmente se suelen asociar a querys de formato SELECT

Para un ejemplo donde existen dos tablas:

  • Alumnos (id (ai not null), nombre (text(255 not null), apellidos (text(255 not null)), telefono (int(8 not null)))
  • Cursos (id (ai not null), nombre (text(255 not null), tutor (text(255 not null)), codigo (int(8 not null)))

Las operaciones de CRUD serían:

Agregar

Mediante sintaxis MySql se ejecuta el método executeUpdate() donde de devuelve un entero con el número de filas que se han visto afectadas por la ejecución de la query

Statement c = (Statement) conn.createStatement();
String sqlInsert = "INSERT INTO usuarios (nombre,apellidos,telefono) VALUES ('Nombre','Apellido',123)";
c.executeUpdate(sqlInsert);
c.close();
conn.close();

Actualizar

Mediante sintaxis MySql se ejecuta el método executeUpdate() donde de devuelve un entero con el número de filas que se han visto afectadas por la ejecución de la query

Statement c = (Statement) conn.createStatement();
String sqlUpdate = "UPDATE usuarios SET nombre = 'Nuevo' WHERE nombre = 'Nombre'";
c.executeUpdate(sqlUpdate);
c.close();
conn.close();

Borrar

Mediante sintaxis MySql se ejecuta el método executeUpdate() donde de devuelve un entero con el número de filas que se han visto afectadas por la ejecución de la query

Statement c = (Statement) conn.createStatement();
String sqlDelete = "DELETE FROM usuarios WHERE nombre = 'Nombre'";
c.executeUpdate(sqlDelete);
c.close();
conn.close();

Seleccionar

Mediante sintaxis MySql se ejecuta el método executeQuery() donde de devuelve un objeto de tipo ResultSet con las filas que cumplen la sentencia query.

Statement c = (Statement) conn.createStatement();
String sqlDSelect = "SELECT nombre,apellidos FROM usuarios WHERE nombre = 'Nombre'";
ResultSet resultSet = c.executeQuery(sqlDSelect);
c.close();
conn.close();

Una vez obtenido el objeto ResultSet hay que recorrerlo y sacar cada una de las filas donde cada unas de las columnas según los tipos. Para poder recorrerlo se utilizan los siguientes métodos

//sitúa el puntero en la primera posición del resultado devulevo
resultSet.first();
//sitúa el puntero en la última posición del resultado devulevo
resultSet.last();
//sitúa el puntero en la siguiente posición del resultado devulevo
resultSet.next();
//sitúa el puntero en la anterior posición del resultado devulevo
resultSet.previous();
//obtiene el tipo de dato indicado de la columna 0 (posición) indicada
resultSet.getArray(0);
//obtiene la posición de la columna cuyo nombre coincide con el nombre dado
resultSet.findColumn("nombre");

El recorrido de un objeto de tipo resultset se hace mediante un bucle while donde se ejecutarán las instrucciones siempre que haya siguiente resultado

Statement c = (Statement) conn.createStatement();
String sqlDSelect = "SELECT nombre, apellidos FROM usuarios WHERE nombre = 'Nombre'";
ResultSet resultSet = c.executeQuery(sqlDSelect);
resultSet.first();
while (resultSet.next()){
    String nombre = resultSet.getString(resultSet.findColumn("nombre"));
    String apellido = resultSet.getString(resultSet.findColumn("apellidos"));
}

PrepareStatement

Un objeto de tipo PrepareStatement permite ejecutar querys donde no se pasan parámetros de forma directa, sino que se agregan al objeto mediante índices (posiciones) y tipos. Esto lo hace algo más eficiente ya que no es el motor de base de datos el que comprueba la sintaxis de cada uno de los tipos de los valores pasados, sino que ya directamente el objeto se los pasa con los datos concretos. Por ejemplo imaginemos que se quiere realizar una inserción en la tabla de alumnos donde tenemos un campo id (int pk autoincrementel), nombre (string) apellido (string) y teléfono (int). La query que le pasaríamos al motor de base de datos sería

INSERT INTO alumnos (nombre, apellidos, telefono) VALUES ('NombreNuevo','ApellidoNuevo',123)

Esta query se ejecutaría mediante un objeto de tipo Statement como se ha visto en el apartado anterior. En este ejemplo el motor de base de datos recibe la query completa y tiene que identificar si cada uno de los datos corresponde con los tipos de las columnas.

Sin embargo con un objeto de tipo PrepareStatement esta comprobación no es necesaria al introducir los tipos según su método.

PreparedStatement ps = conn.prepareStatement("INSERT INTO usuarios (nombre,apellidos,telefono) VALUES (?,?,?)");
ps.setString(1,"NombrePS");
ps.setString(2,"ApellidoPS");
ps.setInt(3,123);
ps.executeUpdate();
ps.close();
conn.close();

Exactamente lo mismo pasaría con una orden de update, delete o select

    public void borrarDatosPS() throws SQLException {
        realizarConexion();
        PreparedStatement ps = conn.prepareStatement("DELETE FROM usuarios WHERE nombre = ?");
        ps.execute();
        ps.close();
        conn.close();
    }
    
    public void actualizarDatosPS() throws SQLException {
        realizarConexion();
        PreparedStatement ps = conn.prepareStatement("UPDATE usuarios SET nombre = 'Nuevo' WHERE nombre = '?'");
        ps.setString(1,"NombreModificado");
        ps.executeUpdate();
        ps.close();
        conn.close();
    }
    
    public void obtenerDatosPS() throws SQLException {
        realizarConexion();
        PreparedStatement ps = conn.prepareStatement("SELECT id, nombre FROM usuarios WHERE nombre = ? AND apellidos =?");
        ps.setString(1,"NombreBuscar");
        ps.setString(2,"ApellidoBuscar");
        ResultSet rs = ps.executeQuery();
        if (rs != null)
        {
            rs.first();
            while (rs.next()){
                rs.getString(rs.getString("nombre"));
                rs.getString(rs.getString("apellidos"));
                
            }
        }
        rs.close();
        conn.close();
    }