Pooling de Conexiones a base de datos con C3P0 y Java

Estándar

Un pool de conexiones a base de datos es una forma de llevar un control de las mismas de modo que al desocupar una conexión, en lugar de cerrar la conexión la tengamos a la mano y se entregue al siguiente objeto que necesite una conexión.

Si bien esto puede sonar innecesario debe de recordar que crear una conexión a base de datos es una de las operaciones mas pesadas que puede efectuar y que las conexiones expiran automáticamente después de un tiempo sin uso, ambas cosas que pueden afectar el rendimiento o estabilidad de su aplicación.

Ahí es donde entra el pool de conexiones ya que este se encargara de reducir el numero de veces que necesite crear una nueva conexión y en caso que esta expire crea una nueva si es necesario.

Pool de conexiones C3P0

Uno de los pools de conexiones mas populares actualmente es el C3P0 proporcionado por Machinery For Change, Inc, este le proporciona todas las funcionalidades esperadas a la vez que se integra con gran facilidad a otros frameworks de Java.

Debido a su popularidad y sencillez de uso nos enfocaremos en como hacer uso de este pool en particular.

Obtener las librerías de c3P0.

Vaya a la pagina oficial del proyecto: http://www.mchange.com/projects/c3p0/ o directamente al repositorio en SourceForge y descargue la versión mas reciente.

En el archivo .zip que descargo vaya a la carpeta lib y extraiga los archivos c3p0-0.9.5.2.jar, c3p0-oracle-thin-extras-0.9.5.2.jar y mchange-commons-java-0.2.11.jar con estos ya podrá usar el pool en su proyecto.

A su vez necesitara de la librería para usar conexiones a base de datos, agregue esta a su proyecto como se ve en la figura 2.

2016-04-18

Figura 1 – Librerías de C3P0.

2016-04-18 (1)

Figura 2 – Librerías del proyecto.

Estos archivos .jar pueden agregarse a un proyecto como ya lo hemos hecho con anterioridad.

Uso del pool C3P0 en un programa.

En el ejemplo que se utilizara para demostrar el uso del pool seguramente notará un par de cosas un tanto inusuales, específicamente que obtendremos el pool de conexiones vía un método getInstance en lugar de un constructor, obtendremos las conexiones desde el pool  y que haremos un uso constante del método close del objeto conexión.

El uso del getInstance es por una razón muy sencilla, haciendo el pool un objeto estático y obteniendo este vía el getInstance podemos tener el *mismo* pool disponible en todo el programa sin necesidad de estar pasando ese objeto a cada una de las clases, se los digo por experiencia, tener que agregar un parámetro extra a cada constructor y crear los getter y setter necesarios se vuelve aburrido de inmediato.

El obtener las conexiones desde el pool es necesario para poder obtener los beneficios de este, fuera de eso se comportan de manera usual por lo que no necesita modificar cómo realiza sus consultas.

Con respecto a llamar el método close esto es necesario para indicar al pool que ya no estamos usando esa conexión, de modo que esté disponible para cuando se solicite, es *vital* que recuerde llamar al método close o que use la estructura try-with-resources proporcionada por Java, ya que el no hacer esto puede trabar su aplicación, ese caso se verá en el ejemplo.

Ejemplo.

El ejemplo que se presentará es muy sencillo, pero presenta los detalles de como crear la clase para manejar el pool  y cómo usar esta en un programa de una forma que, espero, sea lo más legible y sencilla de entender posible.

El ejemplo consistirá en dos clases, una que crea y configura el pool y otra desde la cual realizaremos una serie de consultas a la tabla de base de datos que se ve en la figura 3.

2016-04-20 (2)

Figura 3 – Tabla a presentar.

package c3p0ejemplo;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Connection;

public class PoolC3P0 {
 // Notara que el pool es un miembro *estatico* esto es para evitar duplicidad
 private static PoolC3P0 datasource;
 // Esta es la fuente de datos que conecta con la base de datos
 private final ComboPooledDataSource cpds;

 /**
  * Crea el constructor del pool, notara que este constructor es privado
  * esto con el fin de que podamos controlar cuando se crea el pool
  * @throws IOException
  * @throws SQLException
  * @throws PropertyVetoException
  */
 private PoolC3P0() throws IOException, SQLException, PropertyVetoException {
  // Configuramos la conexion a base de datos
  // Creamos la fuente de datos
  cpds = new ComboPooledDataSource();
  // Que driver de base de datos usaremos
  cpds.setDriverClass("com.mysql.jdbc.Driver");
  // La url de la base de datos a la que nos conectaremos
  cpds.setJdbcUrl("jdbc:mysql://127.0.0.1/");
  // Usuario de esa base de datos
  cpds.setUser("usuario");
  // Contraseña de la base de datos
  cpds.setPassword("contrasena");

  // Configuramos el pool
  // Numero de conexiones con las que iniciara el pool
  cpds.setInitialPoolSize(0);
  // Minimo de conexiones que tendra el pool
  cpds.setMinPoolSize(0);
  // Numero de conexiones a crear cada incremento
  cpds.setAcquireIncrement(1);
  // Maximo numero de conexiones
  cpds.setMaxPoolSize(5);
  // Maximo de consultas
  cpds.setMaxStatements(180);
  // Maximo numero de reintentos para conectar a base de datos
  cpds.setAcquireRetryAttempts(2);
  // Que se genere una excepcion si no se puede conectar
  cpds.setBreakAfterAcquireFailure(true);
 }

 /**
  * Nos regresa la instancia actual del pool, en caso que no halla una instancia
  * crea una nueva y la regresa
  * @return
  * @throws IOException
  * @throws SQLException
  * @throws PropertyVetoException
  */
 public static PoolC3P0 getInstance() throws IOException, SQLException, PropertyVetoException {

  if (datasource == null) {
   datasource = new PoolC3P0();
   return datasource;
  } else {
   return datasource;
  }
 }

 /**
  * Este metodo nos regresa una conexion a base de datos, esta la podemos
  * usar como una conexion usual
  * @return Conexion a base de datos
  * @throws SQLException
  */
 public Connection getConnection() throws SQLException {
  return this.cpds.getConnection();
 }

}
package c3p0ejemplo;

import java.beans.PropertyVetoException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class C3P0Ejemplo {

 /**
  * @param args the command line arguments
  */
 public static void main(String[] args) {
  try {
   // Obtenemos el pool de conexiones
   PoolC3P0 pool = PoolC3P0.getInstance();

   for (int i = 0; i < 10; i++) {
    // Solicitamos una conexion al pool
    Connection cx = pool.getConnection();
    // Creamos nuestro objecto de consulta
    Statement consulta = cx.createStatement();
    // La consulta que ejecutaremos
    String sql = "SELECT * FROM pruebas.prueba";
    // Obtenemos los datos
    ResultSet data = consulta.executeQuery(sql);
    data.next();

    Integer puerto = data.getInt("puerto_serial");
    Integer impresora = data.getInt("puerto_impresora");
    Integer red = data.getInt("puerto_red");
    Integer scaner = data.getInt("puerto_escaner");

    // Los presentamos en pantalla
    System.out.println("Vuelta numero " + i);
    System.out.println("Puerto " + puerto);
    System.out.println("Impresora " + impresora);
    System.out.println("Red " + red);
    System.out.println("Escaner " + scaner);
    System.out.println("");
    System.out.println("");

    // Cerramos la conexion, esto es vital, de no hacerlo el pool creara una nueva conexion
    // pero al cerrar liberamos esa conexion para que el pool la reuse
    cx.close();

    // Un retrazo de 10 segundos para poder ver las conexiones en MySQL Workbench
    Thread.sleep(5000);
   }

  } catch (IOException ex) {
   System.out.println("Error de entrada salida");
  } catch (SQLException ex) {
   System.out.println("Error de conexion a base de datos");
  } catch (PropertyVetoException ex) {
   System.out.println("Error de propiedades");
  } catch (InterruptedException ex) {
   System.out.println("Error de interrupcion de proceso");
  }

 }

}

Ya que ejecute el programa vera que el programa abre una conexión, consulta, presenta los datos, realiza una espera y cierra la conexión, el resultado se vera como la figura 4.

2016-04-20 (1)

Figura 4 – Salida del programa

Como ve el ejemplo pide y cierra conexiones a cada vuelta, mientras el programa se ejecuta acceda a la administración de conexiones de usuario en workbench, notara que la conexión que usamos (identificada por el usuario “usuario”) nunca cambia, no importa cuantas conexiones abramos o cerremos solo se esta usando una como vemos en la figura 5.

2016-04-20 (3)

Figura 5 – Conexiones del usuario

Como un extra modifique la tabla mientras corre el programa y vera que los datos presentados cambian en forma acorde.

Espero que la entrada fuera útil y nos vemos en la próxima.

Anuncios

Obtener los nombres de las columnas de una tabla MySQL con Java

Estándar
mejor_modo

No mas 50 lineas de .getString(“nombre_columna”)

La forma mas común de manejar una base de datos MySQL en Java es usar los objectos Statement y ResultSet para enviar comandos a la misma y obtener el resultado de la consulta, si lo hay. En lo general este metodo funciona muy bien y le da pleno acceso a todas las funcionalidades del MySQL, ya que cada comando que use en MySQL Workbench va a funcionar sin problemas.

El unico inconveniente en este método es precisamente crear los comandos a enviar, pues sera muy comun que tenga que estar concatenando una cantidad muy grande de cadenas de texto y variables con los datos, en especial para los comandos INSERT INTO y UPDATE y si a eso le suma tablas con una enorme cantidad de datos no ha de extrañarle funciones de mas de 50 lineas en las que al menos 30 son solo repeticiones de sql = sql + “campo='” + dato + “‘, “; una y otra y otra vez, por fortuna hay una forma de automatizar la creación de ese comando y la consulta de datos.

SHOW COLUMNS FROM

El comando SHOW COLUMNS FROM <tabla> de MySQL le presenta la información sobre las columnas de la tabla, incluido el nombre de las columnas y como esta es una consulta normal de MySQL podemos ejecutarla desde Java y obtener el resultado.

Ahora, si ya tenemos los nombres de las columnas, en una forma en la que podemos iterar con un ciclo, no deberia ser dificil crear automaticamente la consulta, ¿verdad?, para nada el ejemplo a continuación presentara como hacer esto, con comentarios para detallar que ocurre.

package nombrecampos;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;

public class NombreCampos {   

  public static void main(String[] args) {
    try {
      Connection conexion;
      Statement consulta;            
      ResultSet data;
      ArrayList nombreCampos = new ArrayList<>();
      HashMap<String, Integer> datos = new HashMap<>();
            
      String user = "tecnico";
      String pass = "acceso1987";
            
      // Conectamos con la base de datos

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

      conexion=DriverManager.getConnection(
        "jdbc:mysql://127.0.0.1:3306/pruebas"+"?"
        +"user=" + user + "&" + "password=" + pass + "");
        
      // Obtenemos los nombres de los campos de 
      //la tabla pruebas.prueba

  
      String comandoCampos = "SHOW COLUMNS FROM pruebas.prueba";
      consulta = conexion.createStatement();
      data = consulta.executeQuery(comandoCampos);
            
      while(data.next() == true) {
          
        // El campo Field es el que contiene el nombre 
        // de la columna
        
        System.out.println("Obtenemos el campo " 
        + data.getString("Field"));
          
        nombreCampos.add(  data.getString("Field") );
       }
       consulta.close();
         
       // Como prueba de que podemos usar esos nombres para
       // crear los comandos MySQL obtendremos los datos y 
       // los almacenamos el el HashMap
            
       consulta = conexion.createStatement();
       String comandoDatos = "SELECT * FROM pruebas.prueba;";
       data = consulta.executeQuery(comandoDatos);
            
        while(data.next() == true ) {
          for(String campo : nombreCampos ){
            datos.put( campo , data.getInt(campo));
            }
          }
            
          // Vemos que los datos se obtuvieran bien
          
          System.out.println("Valor de puerto_red " 
                              + datos.get("puerto_red"));

          System.out.println("Valor de isla " 
                              + datos.get("isla"));
            
          consulta.close();
            
          // Ahora cambiaremos unos valores y crearemos el 
          // comando para actualizar
          // la informacion en la base de datos
            
          datos.put("puerto_serial", 10);
          datos.put("puerto_impresora", 9);
          datos.put("puerto_red", 8);
          datos.put("red_enabled", 0);
            
          // Creamos el comando de actualizacion
          
          String comandoActualizacion="UPDATE pruebas.prueba " 
                                      + "SET ";
            
          // Usaremos un ciclo para agregar todos 
          // los campos y sus nuevos valoes
          int i;
          for(i=0; i < nombreCampos.size()-1; i++) {
            String campo = nombreCampos.get(i);            
            comandoActualizacion = comandoActualizacion 
              + campo + "=" + datos.get(campo) + ", ";
          }
            
          // El ultimo campo lo ponemos fuera del ciclo para
          // NO dejar una coma al final, o MySQL regresara error
          String campo = nombreCampos.get(i);
          comandoActualizacion = comandoActualizacion 
              + campo + "=" + datos.get(campo);
            
          // Mostramos el comando y lo ejecutamos
          System.out.println(comandoActualizacion);
          consulta = conexion.createStatement();

          consulta.executeUpdate(comandoActualizacion);            
        
      } catch (ClassNotFoundException ex) {
         System.err.println("Error de driver");
         ex.printStackTrace();
      } catch (SQLException ex) {
         System.err.println("Error de acceso a base de datos");
         ex.printStackTrace();
      }
  }    
}

Las anotaciones de los comentarios (espero) dejen en claro lo que esta ocurriendo en el codigo, lo que aqui hacemos es basicamente lo siguiente:

  1. Nos conectamos a la base de datos
  2. Obtenemos los nombres de las columnas de esa tabla
  3. Las almacenamos en un ArrayList que podamos iterar despues
  4. Usando ese ArrayList sacamos los datos de la tabla con .getInteger, sin tener que escribir los nombres de los campos uno por uno y los guardamos en un HashMap
  5. Mostramos y modificamos ese HashMap
  6. Con ayuda del arrayList creamos el comando UPDATE, de nuevo no tenemos que escribir los nombre de los campos
  7. Actualizamos la base de datos.

Como muestra a continuación estan unas capturas de la base de datos antes de correr el programa, la salida del programa y la base de datos despues de correr el programa.

01_antes

Figura 1 – Base de datos antes de correr el programa

02_salida

Figura 2 – Salida del programa

03_final

Figura 3 – Base de datos despues de correr el programa

Ahora si bien es cierto que puede actualizar la base de datos solo basandose en la posición de la columna, ese metodo me parece muy inseguro, ya que se modifica la tabla podria causar errores, este metodo, al basarse en los nombres de columna, no se vera afectado si agrega un campo nuevo al inicio.

Consultando estado de los eventos en MySQL

Estándar

Al momento de crear un evento en una base de datos MySQL podría quedarle en la cabeza la duda “¿Y si se estará ejecutando?”, después de todo el MySQL no tiene un equivalente al println o un log que le permita revisar eso, por fortuna si cuenta con una tabla donde el estado de los eventos, esta tabla es INFORMATION_SCHEMA.EVENTS.

Consultar esta tabla es bastante sencillo basta con usar la consulta:

SELECT * FROM INFORMATION_SCHEMA.EVENTS

Lo que le mostrara una salida similar a la figura:

Estatus de Eventos

Estado de los Eventos

Esto le presentara todos los eventos que se hallan creado la declaración de estos, el intervalo de ejecución, la fecha de arranque y, aun mas útil, la fecha y hora de la ultima ejecución del mismo, toda esta información nos puede servir para detectar una variedad de problemas, desde un evento mal programado a que el Scheduler del MySQL se halla detenido.

Espero que esta información les sea de utilidad y nos vemos en la próxima entrada.

Error 2006 en MySQL

Estándar

Al momento de llevar a producción una aplicación que acceda a bases de Datos MySQL algo que uno debe de esperar es lo inesperado, desde los problemas mas obvios a los errores mas pintorescos que se pueda imaginar, este es uno de los ultimos.

En el servidor MySQL el error “MySQL server has gone away (error 2006)” se le presentara cuando el tamaño de los datos a procesar exceda el maximo tamaño de paquete que pueda manejar o el servidor tome mas tiempo de lo permitido procesando una consulta en particular, en mi propia experiencia estos casos pueden presentarse cuando el MySQL server se esta ejecutando en una maquina con recursos mas bien modestos.

En cualquiera de los casos la solución de este error es relativamente sencilla, basta con aumentar el tamaño maximo de los paquetes de datos y/o el tiempo de espera para la respuesta del servidor, ambas opciones pueden modificarse desde “Options File” en la configuración del servidor MySQL, como se ve en las figuras 1 y 2.

Figura 1: Tamaño maximo permitido

Figura 1: Tamaño maximo permitido.

Figura 2: Tiempo de espera

Figura 2: Tiempo de espera

Figura 2: Tiempo de Espera.

El modificar estas opciones deberia corregir el problema por completo, pero no tendran ningun efecto hasta que reinicie el servidor MySQL de modo que arranque con las nuevas opciones, si esta en un entorno de producción debe tener cuidado al hacer esto, ya que si bien el reinicio es relativamente veloz, podria causar problemas a aplicaciónes que esten en uso en ese momento o interrumpir servicios, para reiniciar el servidor vaya a “Startup/Shutdown” y, como se ve en la figura 3, desde ahi podria apagar y volver a iniciar el servidor MySQL

Figura 3: Inicio / Apagado de MySQL

Figura 3: Inicio / Apagado de MySQL

Espero que esta entrada halla sido de utilidad y nos vemos en la proxima.

Referencias:

How to fix “MySQL server has gone away” (error 2006)

Mostrar datos de una tabla MySQL con Java Swing

Estándar

Al momento de crear una aplicación que acceda a bases de datos es muy posible que necesite presentar los datos en pantalla via la interfaz gráfica específicamente en una tabla que presente los datos registro por registro, como era de esperar Java tiene las herramientas para hacer eso.

Preparando el proyecto.Las partes de como acceder a una base de datos y como preparar el proyecto para usar MySQL Connector se explican en esta entrada: https://hashblogeando.wordpress.com/2013/10/22/acceder-a-una-base-de-datos-mysql-desde-java/ se recomienda revisarla antes de comenzar.

Datos a presentar

Para este ejemplo se presentaran en pantalla los datos de la tabla mostrada en la figura  1:

Figura 01 - Datos

Figura 01 – Datos

Notara que la tabla solo tiene cuatro columnas, para que todo funcione necesita tener a la mano el nombre de las columnas y los datos de conexión, ya que los necesitara.

Teoría básica.

Para presentar datos en la interfaz gráfica utilizaremos dos clases JTable y DefaultTableModel el primero sirve para presentar datos en la interfaz gráfica en la forma esperada con la cuadricula y títulos de cada columna mientras que el segundo contiene los datos que deseamos presentar, como muchas cosas del java suena mas complejo que lo que deveria, pero a la vez da una mayor flexibilidad en como hacer las cosas y mantiene la separación de datos y presentación.

Uso básico de JTable

La clase JTable no tiene la mayor complicación en su uso, sin embargo hay un detalle que debe de tomar en cuenta cuenta lo que se podría pensar esta clase no tiene barras de desplazamiento incluidas por lo que necesita hacer uso de un objeto JScrollPane para que quepa cómodamente en la ventana.

Para presentar datos en los objetos de esta clase es necesario asignar un modelo que contenga los datos a desplegar, esto es con el metodo setModel.

Uso básico de DefaultTableModel

Los datos presentados por el objeto JTable son controlados por esta clase principalmente los títulos de las columnas y los datos que se presentaran en la tabla, esto ultimo se lleva acabo por medio del método addRow, el cual recibe como argumento un arreglo de objetos los cuales se presentaran en la tabla.

Proyecto

02 - Proyecto

02 – Proyecto

Como notara en el proyecto de ejemplo se usaran dos clases, una que extiende JFrame y contiene la tabla y los accesos a base de datos y otra que contiene el método main, como se menciono al principio de la entrada necesita agregar las librerías del MySQL Connector al proyecto. ahora pasemos al codigo y las anotaciones.

Código

package mx.com.hashSoft;

import java.awt.BorderLayout;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class Tabla extends JFrame{
    /**
     *
     */
    private static final long serialVersionUID = 210601883990408438L;
    private Connection conexion = null;
    private Statement comando = null;
    private ResultSet resultados = null;
    private JTable tabla = null;
    DefaultTableModel modelo = null;
    JScrollPane desplazamiento = null;
    
    /**
     * Obtenemos todos los datos de la tabla juegos;
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    private void leerDatos() throws ClassNotFoundException, SQLException {
        String usuario = “inventario”;
        String passwd = “1973”;
        String instruccion = “SELECT * FROM HashData.juegos”;

        Class.forName(“com.mysql.jdbc.Driver”);
        conexion = DriverManager.getConnection(“jdbc:mysql://127.0.0.1:3306/HashData” + “?” + “user=” + usuario + “&” + “password=” + passwd + “”);
        comando = conexion.createStatement();
        resultados = comando.executeQuery(instruccion);
    }
    
    /**
     * Cierra la conexion con base de datos
     * @throws SQLException
     */
    private void cerrar() throws SQLException {
        conexion.close();        
    }   
    
    public Tabla() {
        // Nombre de las columnas como apareceran en la tabla
        String[] columnas = {“id”, “Consola”, “Nombre”, “Obtenido”};
        tabla = new JTable();
        modelo = new DefaultTableModel();
        desplazamiento = new JScrollPane(tabla);
        int id, consola, obtenido;
        String nombre;
        
        // Parametros de la ventana
        this.setTitle(“Tabla de juegos”);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(new BorderLayout());
        
        // Modelo de la tabla
        modelo.setColumnIdentifiers(columnas);
        
        // Barras de desplazamiento
        desplazamiento.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        desplazamiento.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        
        // Propiedades de la tabla
        tabla.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
        tabla.setFillsViewportHeight(true);        
        
        tabla.setModel(modelo);
        
        // Agregando elementos a la ventana
        this.getContentPane().add(desplazamiento, BorderLayout.NORTH);    
        this.pack();
        
        // Ponemos los datos en la tabla
        
        try {
            // Obtener datos de la tabla
            this.leerDatos();
            
            while(resultados.next() == true) {
                
                id = resultados.getInt(“id”);
                consola = resultados.getInt(“consola”);
                obtenido = resultados.getInt(“obtenido”);
                nombre = resultados.getString(“nombre”);
                
                modelo.addRow( new Object[] {id, consola, nombre, obtenido} );                
            }
            
            this.cerrar();
            
        } catch (SQLException | ClassNotFoundException e) {
            System.out.println(“Error de lectura de BD\n\n”);
            
            e.printStackTrace();
        }
    }
}

package mx.com.hashSoft;
public class MostrarDatos {   
    static public void main(String[] args) {       
        Tabla ventana = new Tabla();       
        ventana.setVisible(true);        
    }
}

Como es costumbre en las entradas de este blog , las lineas mas relevantes se marcaron en rojo y su función se detallara a continuación, cabe denotar que el como se accedió a la base de datos se explico en otra entrada.

String[] columnas = {“id”, “Consola”, “Nombre”, “Obtenido”}; – Declaramos cuales seran los nombres de las columnas que se presentaran en la tabla.

tabla = new JTable(); – Creamos un objeto JTabla

modelo = new DefaultTableModel(); – Creamos el modelo de datos que usaremos en la tabla.

desplazamiento = new JScrollPane(tabla); – Creamos el panel con barras de desplazamiento que contendrá a la tabla

modelo.setColumnIdentifiers(columnas); – Le indicamos al modelo que nombres tendrán las columnas.

desplazamiento.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
desplazamiento.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); – Con esto establecemos que aparescan las barras de desplazamiento cuando se necesiten

id = resultados.getInt(“id”);
consola = resultados.getInt(“consola”);
obtenido = resultados.getInt(“obtenido”);
nombre = resultados.getString(“nombre”); – Obtenemos los datos de la base de datos almacenándolos en variables del tipo adecuado

 modelo.addRow( new Object[] {id, consola, nombre, obtenido} ); – La linea principal, con esto agregamos un nuevo renglón al modelo y por tanto a la tabla se pasa como argumento un arreglo de objectos con lo que deseamos agregar, aparecieran en el orden en el que se introduzcan aquí.

Resultado

Figura 03 - Salida

Figura 03 – Salida

 

Una vez que ejecute la clase MostrarDatos, sobra decir que necesitara o recrear la tabla de la figura 1 y colocar los datos de conexión correctos vera algo como la figura 3, presentando los datos de la tabla, de modo que si modifica la tabla y vuelve a ejecutar el programa estos cambiaran de forma acorde.

Espero que esta entrada halla sido de utilidad y que le de una idea de como implementar y extender el como presentar datos en pantalla, nos vemos en la siguiente entrada.

 

Instalación de MySQL en Fedora Linux 20

Estándar

Si bien la instalación del servidor MySQL es un proceso muy sencillo en Fedora Linux, una serie de cambios Fedora 20 hacen que el proceso sea un poco mas elaborado de lo que solia ser, esto es mas una molestia que otra cosa, pero puede causar confusión si se basa en tutoriales que describen el proceso en una version anterior, por esta razón escribo este tutorial de como realizar la instalación de MySQL, el servidor y MySQL Workbench en Fedora Linux 20.

Cambios en el manejador de paquetes.

Uno de los cambios mas evidentes es el hecho que la aplicación para instalar y desinstalar paquetes a cambiado en favor de la aplicación desarrollada por el proyecto GNOME, en general la aplicación se siente como una mejora de la versión anterior, pero por al parecer maneja la lista de paquetes de otra forma o aun le falta un poco de pulido, en ambos casos si busca MySQL en el obtiene el resultado de la figura 1

Figura 1 - Resultados de la busqueda

Figura 1 – Resultados de la busqueda

Varios resultados de interes, pero ni una mención del servidor MySQL, esto pareceria preocupante, pero si usamos la linea de comandos con el comando yum search MySQL obtenemos una muy notable lista de paquetes disponibles, como vemos en la figura 2.

Figura 2 - Resultados de yum search

Figura 2 – Resultados de yum search

Instalando el servidor MySQL y Workbench.

De estos paquetes los que necesitara para obtener el servidor MySQL y sus utilerias son los siguientes:

  1. community-mysql
  2. community-mysql-server
  3. mysql-utilities
  4. mysql-connector-java

Si ya ha usado MySQL en plataformas Windows seguramente le extrañara que no se halla mencionado el entorno MySQL Workbench, el cual es una forma muy practica y sencilla de administrar el servidor, respaldar y restaurar bases de datos y hacer consultas, este paquete ya no esta disponible desde el repositorio de software debido a problemas de licencias, puede instalarlo en su versión mas reciente descargando el paquete directamente desde la pagina oficial , la cual es: http://dev.mysql.com/downloads/tools/workbench/ simplemente seleccione Fedora como plataforma y descargue la versión adecuada para su sistema.

Una vez que halla descargado el paquete .rpm adecuado proceda a instalarlo con ayuda del comando yum localinstall <archivo.rpm> esto instalara el paquete y descargara todas las dependencias adecuadas, una vez que halla instalado todos los paquetes puede abrir MySQL Workbench, el cual se vera como en la figura 3

Configurando el servidor MySQL.

Figura 3 - MySQL Workbench

Figura 3 – MySQL Workbench

Ya que habra workbench debera de definir la conexión con el servidor local, para esto presione el simbolo + a la derecha del mensaje “MySQL Connections”, lo cual le presentara el asistente mostrado en la figura 4

Figura 4 - Nueva conexión Mysql

Figura 4 – Nueva conexión Mysql

Pero si intenta probar la conexión con el servidor con el botón “Test Connection” recibira el mensaje de error mostrado en la figura 5

Figura 5 - No se pudo conectar

Figura 5 – No se pudo conectar

Esto se debe a que no tenemos corriendo el servicio mysql, para inicializarlo necesita ejecutar como administrador el comando: service mysqld start este iniciara el servicio si bien con esto ya podríamos configurar la conexión desde Workbench es recomendable que configure la contraseña de acceso para el usuario root, ya que de este modo podra usar las funciones de Workbench para configurar las demas opciones, para lograr esto use el comando: mysqladmin -u root password ‘<contraseña>’ , siempre y cuando su instalación aun no tenga establecida la contraseña de root con este comando la establecera.

Ahora que tenemos el servidor MySQL corriendo y la contraseña de root establecida podemos volver a intentar configurar la conexión, para este caso sugiero usar el nombre “localhost”, ya que lo especifique presione “Test Connection”, aparecerá un dialogo solicitando la contraseña de root como se ve en la figura 6.

Figura 6 - Prueba de conexión

Figura 6 – Prueba de conexión

Escriba la contraseña en el dialogo y si es correcta aparecerá un mensaje como en la figura 7

Figura 7 - Conexión exitosa

Figura 7 – Conexión exitosa

Cierre ese dialogo y presione OK para guardar la conexión, ahora esta aparcera en la pantalla, como puede ver en la figura 8

Figura 8 - Conexión al servidor

Figura 8 – Conexión al servidor

Y para acceder solo de doble click y proporcione la contraseña del usuario root, lo que le presentara el entorno de trabajo propiamente hablando como aparece en la figura 9

Figura 9 - Workbench

Figura 9 – Workbench

Espero que esta entrada halla sido de utilidad y nos vemos en la próxima.

Acceder a una base de datos MySQL desde Java

Estándar

Las bases de datos se han vuelto un elemento común en prácticamente todos los proyectos de software y existe una gran cantidad de formas de hacerlo, desde métodos que relacionan la salida de la consulta directamente a objetos a métodos muchos mas sencillos que usan directamente comandos de SQL, uno de estos últimos sera el tema de esta entrada.

Conector MySQL

Antes de comenzar necesitara tener un servidor MySQL y una base de datos a la que pueda acceder, por el momento no entrare en estos detalles y asumiré que ya los tiene, de no ser el caso basta con un comentario pidiendo mas detalles para crear una entrada del tema, a la vez necesitara de una libreria en Java para acceder a la base de datos el conector a MySQL, este puede ser descargado gratuitamente desde esta dirección: http://dev.mysql.com/downloads/connector/j/3.0.html una ves que tenga los elementos de base de datos y el conector podemos comenzar.

Figura 1 - Base de datos

Figura 1 – Base de datos

Creando proyecto en Eclipse

Una vez que halla descargado el conector MySQL abralo y extraiga el archivo mysql-connector-java y agregelo a las librerias del proyecto, una forma de hacer esto esta descrita en una entrada anterior de este mismo blog: iText, Generación de archivo Pdf en Java, ahi encontrara el procedimiento para agregar una libreria a un proyecto en Eclipse, ya que halla agregado la libreria cree una clase Java en el paquete mx.com.hashDevel llamada AccesoDB el codigo de esta se presenta a continuación con las lineas relevantes resaltadas en rojo:

package mx.com.hashDevel;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class AccesoDB {
    private Connection conexion = null;
    private Statement comando = null;    
    private ResultSet resultados = null;
    
    /**
     * Inicia la conexion a la base de datos con un nombre de usuario y
     * contraseña predefinidos
     * @throws Exception
     */
    public void iniciarConexion() throws Exception
    {
        String usuario=”inventario”;
        String passwd = “1973”;
        try{
            Class.forName(“com.mysql.jdbc.Driver”);
            
            conexion = DriverManager
                    .getConnection(“jdbc:mysql://127.0.0.1:3306/juegos”+ “?” + “user=”
                            + usuario + “&” + “password=” + passwd + “”);
            
        }catch(Exception e)
        {
            System.err.println(“Error al inciar la conexion a base de datos\t\t”);           
            e.printStackTrace();           
            throw e;
        }
    }
    
    /**
     * Consulta los datos en la tabla juegos, obtiene todos
     * @throws SQLException
     */
    public void consultarDatos() throws SQLException
    {
        String instruccion = “SELECT * FROM juegos.juegos”;
        try {
            comando = conexion.createStatement();           
            resultados = comando.executeQuery(instruccion);
        } catch (SQLException e) {            
            e.printStackTrace();            
            throw e;
        }        
    }
    
    public void cerrarConexion() throws SQLException
    {
        try {
            conexion.close();
        } catch (SQLException e) {
            e.printStackTrace();
            throw e;
        }
    }
    
    public void imprimirDatos() throws SQLException
    {
        int sistema;
        int obtencion;
        String nombre;
        
        while(resultados.next())
        {
            try {            
                sistema = resultados.getInt(“consola”);
                obtencion = resultados.getInt(“obtenido”);
                nombre = resultados.getString(“nombre”);
            } catch (SQLException e) {
                e.printStackTrace();
                throw e;
            }
            System.out.print(nombre + “\t\t\t”);           
            if(sistema == 1)
                System.out.print(“Nintendo DS\t”);
            else if(sistema == 2)
                System.out.print(“Nintendo 3DS\t”);
            else
                System.out.print(“Xbox 360\t”);
                        
            if(obtencion == 1)
            {
                System.out.println(“Nuevo”);
            }
            else
            {
                System.out.println(“Segunda mano”);
            }           
        }    
    }
}

Esta clase contiene las funciones necesarias para acceder a la base de datos, yendo desde inicial la conexión con la base de datos a leer e imprimir los datos en pantalla, las lineas resaltadas en rojo son las que acceden o inicializan las funciones en la base de datos, y se detallaran a continuación:

 conexion = DriverManager.getConnection(“jdbc:mysql://127.0.0.1:3306/juegos”+ “?” + “user=”  + usuario + “&” + “password=” + passwd + “”);  Esta linea de codigo genera la conexión con la base de datos MySQL al parametro que se le pasa es el comando de conexión, una cadena de texto la cual debe de estar en el formato: jdbc:mysql://<Direccion del servidor>:<puerto>/<esquema>?user=<usuario>&password=<contraseña> en caso de error se genera una excepción.

comando = conexion.createStatement();  Generamos un objeto Statement a traves del cual podremos enviar consultas a la base de datos indicada por el objeto conexión

resultados = comando.executeQuery(instruccion); Ya que se tiene el objeto Statement podemos usar este para enviar consultas a la base de datos con esta instrucción, esta a su vez nos regresara los resultados de la consulta como un objeto ResultSet

conexion.close(); Cierra la conexión a la base de datos liberando los recursos en uso y la conexión

 sistema = resultados.getInt(“consola”); Ya que tengamos los resultados de la consulta a la tabla podemos obtener el contenido del campo cuyo nombre es pasado como argumento en forma de un entero, los objectos ResultSet tiene metodos get para cada tipo de datos soportado or MySQL de modo que es la forma adecuada de obtener estos.

resultados.next() Avanza al siguiente registro de los resultados de la consulta regresando true si aun hay resultados y false cuando ya se esta al final de los registros

Ahora tambien cree la clase listado en el mismo paquete, esta simplemente llamara los metodos de AccesoDB

package mx.com.hashDevel;

public class listado {
    
    static public void main(String[] args)
    {
        AccesoDB acceso = new AccesoDB();
        
        try{
            acceso.iniciarConexion();
            acceso.consultarDatos();
            acceso.imprimirDatos();
            acceso.cerrarConexion();
            
        }catch(Exception e)
        {
            System.err.println(“Error”);
        }
    }
}
Antes de ejecutar el programa recuerde modificarlo para la base de datos que tenga a la mano, o si lo prefiere recree la tabla juegos, los elementos de esta son:

  1. indice, tipo int, clave primaria
  2. consola, tipo int, valores usados 1, 2 y 3
  3. nombre, varchar(75)
  4. obtenido, int, valores validos 1 y 2

Hecho esto ejecute el programa, la salida debera ser similar a la Figura 3

Figura 3 - Salida del programa

Figura 3 – Salida del programa

Y si modifica los datos de la tabla, como se ve en la figura 4

Figura 4 - Modificaciones a los datos

Figura 4 – Modificaciones a los datos

Los resultados se modificaran de forma acorde cuando vuelva a correr el programa

Figura 5 - Nuevos resultados

Figura 5 – Nuevos resultados

Notara que los datos en efecto se actualizaron acorde a la base de datos.

Espero que esto halla sido útil y nos vemos en una próxima entrada