Grabar Imagen en Base de Datos Utilizando JDBC

GRABAR IMAGEN EN BASE DE DATOS UTILIZANDO JDBC
Software a Utilizar
  • NetBeans 6.9
  • MySQL 5.1
Tipo de Aplicación

Para este ejercicio se creará una aplicación de tipo Cliente/Servidor cuya interfaz se ilustra a continuación:

Tipo de Dato

Para grabar una imagen en una base de datos MySQL debemos utilizar el tipo de dato BLOB, para este caso utilizaremos la tabla PRODUCTO cuya estructura se muestra a continuación:

mysql> describe producto;
+-----------------+---------------+------+-----+---------+----------------+
| Field           | Type          | Null | Key | Default | Extra          |
+-----------------+---------------+------+-----+---------+----------------+
| PRO_ID          | int(11)       | NO   | PRI | NULL    | auto_increment |
| AUT_ID          | int(11)       | NO   | MUL | NULL    |                |
| CAT_ID          | int(11)       | NO   | MUL | NULL    |                |
| EDI_ID          | int(11)       | NO   | MUL | NULL    |                |
| PRO_NOMBRE      | varchar(100)  | NO   |     | NULL    |                |
| PRO_DESCRIPCION | text          | YES  |     | NULL    |                |
| PRO_STOCK       | int(11)       | NO   |     | NULL    |                |
| PRO_PRECIO      | decimal(10,2) | NO   |     | NULL    |                |
| PRO_FOTO        | blob          | YES  |     | NULL    |                |
+-----------------+---------------+------+-----+---------+----------------+
9 rows in set (0.04 sec)
Clase Entity

La clase entity para la tabla PRODUCTO quedaría implementada de la siguiente manera:

package dao.entity;

     private int id;
     private int autor;
     private int categoria;
     private int editorial;
     private String nombre;
     private String descripcion;
     private int stock;
     private double precio;
     private byte[] foto;

     // Implementar los métodos getters y setters
}

Para la columna de tipo blob se crea un campo de tipo ARRAY de BYTES.

Capa de Lógica de Persistencia

El método que corresponde a la capa de persistencia que crea un nuevo producto en la base de datos se implementa de la siguiente manera:

package dao.componentes;

import dao.database.AccesoDB;
import dao.entity.Producto;
import dao.interfaces.IProductoDAO;
import excepcion.TiendaException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;


public class ProductoDAO implements IProductoDAO {

  public void crear(Producto prod) throws TiendaException {
    Connection cn = null;
    PreparedStatement pstm = null;
    try {
        cn = AccesoDB.getConnection();
        cn.setAutoCommit(false);
        String query = "insert into producto(AUT_ID,CAT_ID,EDI_ID,PRO_NOMBRE," +
                    "PRO_DESCRIPCION,PRO_STOCK,PRO_PRECIO,PRO_FOTO) " +
                    "values(?,?,?,?,?,?,?,?)";
        pstm = cn.prepareStatement(query);
        pstm.setInt(1, prod.getAutor());
        pstm.setInt(2, prod.getCategoria());
        pstm.setInt(3, prod.getEditorial());
        pstm.setString(4, prod.getNombre());
        pstm.setString(5, prod.getDescripcion());
        pstm.setInt(6, prod.getStock());
        pstm.setDouble(7, prod.getPrecio());
        pstm.setBytes(8, prod.getFoto());
        pstm.executeUpdate();
        cn.commit();
    } catch (Exception e) {
        try {
             cn.rollback();
        } catch (Exception e1) {
        }
        throw new TiendaException(e.getMessage());
    } finally {
        try {
             pstm.close();
        } catch (Exception e) {
        }
    }
  }

  . . .
  . . .
}
Acceso a la Capa DAO

Para acceder a la capa DAO se utiliza una capa model implementada de la siguiente manera:

package model;

import dao.componentes.ProductoDAO;
import dao.entity.Producto;
import excepcion.TiendaException;
import java.util.List;

public class CatalogoModel {

     public void crearProducto( Producto prod) throws TiendaException{
          new ProductoDAO().crear(prod);
     }

     . . .
     . . .
}
Implementación de la Capa View

Primero se debe seleccionar el archivo para lo cual se ha implementado el botón Buscar [...], el script es el siguiente:

private void btnBuscarFotoActionPerformed(java.awt.event.ActionEvent evt) {                                             

  JFileChooser openFile = new JFileChooser();
  int returnValue = openFile.showOpenDialog(this);
  if (returnValue == JFileChooser.CANCEL_OPTION) {
      return;
  }
  File archivo = openFile.getSelectedFile();
  this.txtFoto.setText(archivo.getAbsolutePath());
  ImageIcon tmp = new ImageIcon(archivo.getAbsolutePath());
  ImageIcon imagen = new ImageIcon(tmp.getImage().getScaledInstance(
  this.lblFoto.getWidth(),
  this.lblFoto.getHeight(),
  Image.SCALE_DEFAULT));
  this.lblFoto.setIcon(imagen);

}

Y para grabar el registro en la base de datos se ha implementado el botón Grabar, el script es el siguiente:

private void btnGrabarActionPerformed(java.awt.event.ActionEvent evt) {                                         

  try {

      Producto prod = new Producto();
      prod.setAutor(listaAutores.get(cboAutor.getSelectedIndex()).getId());
      prod.setCategoria(listaCategorias.get(cboCategoria.getSelectedIndex()).getId());
      prod.setEditorial(listaEditoriales.get(cboEditorial.getSelectedIndex()).getId());
      prod.setNombre(txtNombre.getText());
      prod.setDescripcion(txtDescripcion.getText());
      prod.setStock(Integer.parseInt(txtStock.getText()));
      prod.setPrecio(Double.parseDouble(txtPrecio.getText()));

      // Obtener la imagen
      File archivo = new File(this.txtFoto.getText());
      byte[] imgFoto = new byte[(int) archivo.length()];
      InputStream input = new FileInputStream(archivo);
      input.read(imgFoto);
      prod.setFoto(imgFoto);

      model.crearProducto(prod);
      utilitarios.Util.showMessage("Producto creado en la base de datos satisfactoriamente.");
      limpiarFormulario();

  } catch (Exception e) {
      utilitarios.Util.showError("ERROR: " + e.getMessage());
  }

} 
Código Fuente de la Aplicación

Para obtener la aplicación ejemplo utilice el siguiente enlace:

Descargar Código Fuente de la Aplicación
CODIGO FUENTE
En esta sección te presento un video de una aplicación CLIENTE-SERVIDOR.
Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.



4 comentarios:

  1. Gustavo, es un buen articulo, pero es importante indicar que el tipo de dato BLOB de MYSQL soporta 2^16 = 64kb y si desean almacenar fotos con un tamaño superior se recomienda usar MEDIUMBLOB que soporta 2^24 = 16MB.

    Saludos

    Ricardo Marcelo

    ResponderEliminar
  2. Es correcta tu observación Ricardo.

    También se debería tener en cuenta que para una tienda se utilizan archivos de imagenes pequeños, sobre todo si se quiere publicar en Internet.

    Gustavo Coronel

    ResponderEliminar
  3. Gustavo, mi recomendación sería almacenar la imagen en diferentes tamaños:

    PRO_FOTO_LARGE MEDIUMBLOB
    PRO_FOTO_MEDIUM MEDIUMBLOB
    PRO_FOTO_SMALL BLOB (imagen en miniatura - Thumbnail)

    El proceso de redimensionar la imagen se haría desde Java.

    ---------------------
    Usando AWT (Toolkit)
    ---------------------
    Image imagen,imagenSmall;

    // Cargar la imagen
    imagen = Toolkit.getDefaultToolkit().getImage( "javaPOO.jpg");

    // Redimensionar la imagen
    imagenSmall = imagen.getScaledInstance(100,100,Image.SCALE_AREA_AVERAGING);

    --------------------------------
    usando JAI (Java Advanced Imaging)
    --------------------------------
    // Cargar la imagen
    BufferedImage imagen = ImageIO.read(new File("javaPOO.jpg"));

    //Redimensionar la imagen
    Image imagenSmall = resize(image, 100, 100);


    // Método para redimensionar imagen
    private BufferedImage resize(BufferedImage image, int width, int height) {

    BufferedImage resizedImage = new BufferedImage(width, height,
    BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = resizedImage.createGraphics();
    g.drawImage(image, 0, 0, width, height, null);
    g.dispose();

    return resizedImage;
    }

    Con JAI se tiene mayor flexibilidad por que es el framework para el tratamiento de imágenes que incorpora Java.

    Saludos

    Ricardo Marcelo

    ResponderEliminar
  4. Gracias por el aporte Profesor me ayudo mucho ,espero siga aportando con mas temas

    Saludos
    Felipe Carrillo

    ResponderEliminar