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.



Patron MVC con PHP

PATRÓN MVC CON PHP
Fundamento

El patrón MVC divide una aplicación Web en tres capas:

Vista: Se encarga de generar el HTML que se envía al browser.

Controlador: Recibe y procesa los requerimiento del usuario y comunica los resultados a la vista para que los envíe al browser.

Modelo: Implementa la lógica del negocio.

La siguiente figura muestra un diagrama de bloques del funcionamiento de este patrón.

Ejemplo Ilustrativo

Para este ejemplo estoy utilizando NetBeans 6.8.

El objetivo de este ejemplo es implementar una aplicación que permita realizar una suma o una multiplicación.

La estructura de la solución es la siguiente:

La clase Session se utiliza para manejar datos de sesión:

class Session {

   public static function existsAttribute($name){

      $rpta = FALSE;

      if( isset( $_SESSION[$name] ) ){

         $rpta = TRUE;

      }

      return $rpta;

    }

   public static function getAttribute($name) {

      $rpta = null;

      if( self::existsAttribute($name) ){

         $rpta = $_SESSION[$name];

      }

      return $rpta;

   }


   public static function getAttribute2($name) {

      $rpta = null;

      if( self::existsAttribute($name) ){

         $rpta = $_SESSION[$name];

         unset( $_SESSION[$name] );

      }

      return $rpta;

   }


   public static function setAttribute($name, $value) {

      $_SESSION[$name] = $value;

   }

}

La clase Matematica implementa la lógica, en este caso las dos operaciones: sumar y multiplicar.

class Matematica {

   public function suma($n1, $n2){

      $su = $n1 + $n2;

      return $su;

   }

   public function producto($n1, $n2) {

      $pr = $n1 * $n2;

      return $pr;

   }

}

El programa main.php implementa el formulario:

<?php

   session_start();

   require_once '../util/Session.php';


   $n1 = Session::getAttribute2("num1");

   $n2 = Session::getAttribute2("num2");

   $rpta = Session::getAttribute2("rpta");

   $action = Session::getAttribute2("action");

?>

<html>

   <head>

      <title>Operaciones Simples</title>

   </head>

   <body>

      <h1>Operaciones Simples</h1>

      <form method="post" action="../controller/Controller.php">

         <div>

            <label>Operacion</label>

            <select name="action">

               <option value="sumar">Suma</option>

               <option value="multiplicar">Producto</option>

            </select>

         </div>

         <div>

            <label>Número 1</label>

            <input type="text" name="num1">

         </div>

         <div>

            <label>Número 2</label>

            <input type="text" name="num2">

         </div>

         <div>

            <input type="submit" value="Procesar">

         </div>

      </form>

      <div>

         <table>

            <tr>

               <td>Action :</td>

               <td><?php echo($action); ?></td>

            </tr>

            <tr>

               <td>Num 1 :</td>

               <td><?php echo($n1); ?></td>

            </tr>

            <tr>

               <td>Num 2 :</td>

               <td><?php echo($n2); ?></td>

            </tr>

            <tr>

               <td>Rpta :</td>

               <td><?php echo($rpta); ?></td>

            </tr>

         </table>

      </div>

   </body>

</html>

En el programa tenemos un control de tipo SELECT, al que se le ha dado el nombre ACTION, este este control que comunica al controlador el método a ejecutar.

La clase Controller recibe los datos del formulario, entre ellos el método a ejecutar, hace uso del Model para resolver el problema y se comunica con el View para que genere el HTML que irá al browser.

El script de la clase controller es el siguiente:

<?php

session_start();
require_once '../model/Matematica.php';

require_once '../util/Session.php';
$action = $_REQUEST["action"];

$obj = new Controller();

$target = call_user_func(array($obj,$action));

header("location: $target");

return;

class Controller {

   public function sumar() {

      $n1 = $_REQUEST["num1"];

      $n2 = $_REQUEST["num2"];

      $mate = new Matematica();

      $rpta = $mate->suma($n1, $n2);

      Session::setAttribute("num1", $n1);

      Session::setAttribute("num2", $n2);

      Session::setAttribute("rpta", $rpta);

      Session::setAttribute("action", "Sumar");

      return "../view/main.php";

   }

   public function multiplicar() {

      $n1 = $_REQUEST["num1"];

      $n2 = $_REQUEST["num2"];

      $mate = new Matematica();

      $rpta = $mate->producto($n1, $n2);

      Session::setAttribute("num1", $n1);

      Session::setAttribute("num2", $n2);

      Session::setAttribute("rpta", $rpta);

      Session::setAttribute("action", "Multiplicar");

      return "../view/main.php";

   }

}

?>

Como podemos apreciar, la programación del controlador es bastante sencillo, el campo action podría ser un campo oculto en un formulario, incluso su valor puede ser manipulado con JavaScript y también se puede manejar con AJAX.

CODIGO FUENTE
En esta sección te presento un video de una aplicación web desarrollada SPRING FRAMEWORK y MYSQL.
Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.



Patron de Diseño Singleton

PATRÓN DE DISEÑO SINGLETON Contexto

Existen escenarios donde la aplicación solo necesita emplear una única instancia (objeto) de una clase, y esta instancia debe ser accesible desde diferentes partes del sistema.
Las clases que cumplen estas características suelen tener alguna de estas funciones:
  • Controlar el acceso a un recurso que por su naturaleza no admite el acceso concurrente (impresora, socket, fichero).
  • Obtener referencias de clases que actúan como servidoras de recursos (pool de conexiones).
  • Ejecutar código carente de estado (si el estado no cambia solo necesitamos una instancia).
  • Mantener un estado que debe ser globalmente único.
Por ejemplo, un sistema de log se ajusta a estas car
acterísticas porque:
  • Controla el acceso al recipiente de la información de log.
  • Toda la información del log se envía a través de un punto único.
  • Su único estado es la configuración, que es global y no suele variar.
Problema
Necesitamos crear una instancia de un clase que sea accesible globalmente, y que sea única.
Solución
El patrón Singleton proporciona la siguiente solución:
  • Hacer que la clase provea una instancia de sí misma.
  • Permitir que otros objetos obtengan esa instancia, mediante la llamada a un método de la clase.
  • Declarar el constructor como privado, para evitar la creación de otros objetos.
El diagrama UML correspondiente es muy simple y se muestra en la siguiente figura.

Este diagrama UML muestra como se implementa el patrón Singleton en una clase. Contiene una propiedad estática (el subrayado indica que es un método de clase) de nombre instancia, y que el método getInstancia() retorna un objeto de la misma clase.
Según la notación UML el número 1 en la esquina superior derecha, indica que solamente habrá una instancia de esta clase. El signo "-" en el constructor, lo señala como privado. Esto consigue que nadie aparte de la propia clase, pueda crear una instancia.
Implementación en PHP
Una primera implementación (GoF) de este patrón considera la instanciación de la clase en el método getInstancia(), tal como se ilustra a continuación:
class Demo{ 

    private static $instancia = null;  

    public static function getInstancia(){  

        if( self::$instancia == null ){  
            self::$instancia = new Demo();  
        }  
        return self::$instancia;  

    }  

    private function __construct() {  
    } 

    . . .   . . .  

}
Una segunda implementación considera la instanciación de la clase en la misma instrucción donde se declara la variable $instancia, tal como ilustra a continuación:

class Demo{ 

    private static $instancia = new Demo();  

    public static function getInstancia(){  
        return self::$instancia;  
    }  

    private function __construct() {  
    } 

    . . .   . . .  

}
El acceso a la instancia se realiza de la siguiente manera:
$demo = Demo::getInstancia();
Implementación en Java
Una primera implementación (Gof) de este patrón considera la instanciación de la clase en el método getInstancia(), tal como se ilustra a continuación:
public class Demo{ 

    private static Demo instancia = null;  

    public static Demo getInstancia(){  

        if( instancia == null ){  
            instancia = new Demo();  
        }  
        return instancia;  

    }  

    private Demo() {  
    } 

    . . .   . . .  

}
Una segunda implementación considera la instanciación de la clase en la misma instrucción donde se declara la variable instancia, tal como ilustra a continuación:
public class Demo{

private static Demo instancia = new Demo(); 

public static Demo getInstancia(){ 
return instancia; 
} 

private Demo() { 
}

. . .   . . . 

}
El acceso a la instancia se realiza de la siguiente manera:

    Demo demo = Demo.getInstancia();
Comentarios

Si estamos en un ambiente de un solo hilo (single-thread) la primera implementación es suficiente. En contrapartida, tiene serios problemas en entornos multihilo (multi-thread) dado que, debido a cuestiones de sincronización y concurrencia, puede crearse más de una instancia. ¿Cómo puede ser esto posible? Imaginemos que dos hilos evalúan la condición $instancia == null ( en Java: instacia == null ) y en ambos casos es verdadera. En este caso, ambos hilos crearán la instancia, violando el propósito del patrón Singleton.
Para solucionar el problema de que existe la posibilidad de crear mas de una instancia en entornos multihilo puede utilizar la segunda implementación.

CÓDIGO FUENTE

En esta sección te presento un video de una aplicación web desarrollada SPRING FRAMEWORK y MYSQL.

Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.