jueves, febrero 24, 2011

Java - Aplicación Web, Carrito de Compras Parte II - Creación del Modelo


"Si usa algún código del siguiente tutorial, den el icono de ME GUSTA del Facebook que se encuentra en su mano derecha, para que se vuelva Seguidor del Blog y también comentenos que tal les pareció el tutorial"

1. Entorno


  • MySQL 5.1.
  • NetBeans IDE 6.9.1
  • Apache Tomcat
  • JDK 1.6.0 - 21

2. Introducción


El modelo es la representación específica de la información con la cual el sistema opera. En resumen, el modelo se limita a lo relativo de la vista y su controlador facilitando las presentaciones visuales complejas. El sistema también puede operar con más datos no relativos a la presentación, haciendo uso integrado de otras lógicas de negocio y de datos afines con el sistema modelado. Acá crearemos nuestros JavaBeans y las clases que se encargaran de llamar a los procedimientos almacenados que hemos creado en nuestra base de datos BDTutorial que esta en MySQL 5.1.. Para comunicar Java con Base de datos usamos lo que comúnmente se conoce como JDBC y para ejecutar consultas o inserciones a nuestra base de datos usamos las interfaces java.sql.Statement que espera que se le pase una sentencia SQL de forma completa por ejemplo "insert into producto values(1,'valor01')", para ejecutar sentencias preparadas se utiliza la interfaz java.sql.PreparedStatement que en los lugares donde se deben de poner los valores para la sentecia SQL se representan entre ? para después poder asignar sus valores respectivos por ejemplo "insert into producto values(?,?)" y la ultima clase para llamar a procedimientos almacenados es la clase java.sql.CallableStatement que es la que utilizaremos para este tutorial

3. Creando el Proyecto


3.1. Proyecto en Netbeans

Primero debemos de crear un proyecto web en Netbeans y para eso abriremos el Netbeans y buscaremos el menu File y luego New Project. Y seleccionaremos que deseamos crear un proyecto del tipo Web Application
















De ahí presionamos el botón Next y nos pedirá que pongamos un nombre a nuestro proyecto y lo llamaremos CarritoComprasJSP

















Luego nos pedirá que seleccionamos en que servidor queremos que se ejecute nuestro proyecto web. En este caso lo ejecutaremos en el servidor de Apache Tomcat
















3.2. Estructura del proyecto

Para explicar la estructura que vamos a tener del proyecto, les presento el siguiente gráfico que nos indicara como se distribuirá el Modelo, el Controlador y la Vista















4. Desarrollo


4.1. Creando el Paquete

Primero debemos de crear nuestro paquete que se llamara Modelo. En el gráfico se explica como crear el paquete


















Y al paquete lo llamaremos Modelo

4.2. Creando los JavaBeans

Para crear los JavaBeans debemos de crear las clases que tendran la misma estructura de las tablas de nuestra base de datos, eso quiere decir que si por ejemplo en alguna tabla de nuestra base de datos tenemos una columna del tipo Varchar en Java tendriamos una variable del tipo String, si tenemos un variable del tipo Decimal en Java seria double. Para eso hacemos clic derecho en nuestro paquete que se llama Modelo, de ahi nos vamos a New y seleccionamos Java Class

4.2.1. Clase Producto

La clase Producto tiene la misma estructura de nuestra tabla Producto de nuestra base de datos, a continuación les comparto el código fuente de la clase.


package Modelo;

//@author Henry Joe Wong Urquiza
 
public class Producto {
    //Las columnas que tiene la tabla Producto
    private int codigoProducto;
    private String nombre;
    private double precio;
    //Constructor de la clase sin parametros
    public Producto() {
    }
    //Constructor de la clase con parametros
    public Producto(int codigoProducto, String nombre, double precio) {
        this.codigoProducto = codigoProducto;
        this.nombre = nombre;
        this.precio = precio;
    }
    //Metodo toString de la clase que nos retorna
    //el nombre del producto
    @Override
    public String toString() {
        return nombre.toUpperCase();
    }
    //Metodos get y set de la clase
    public int getCodigoProducto() {
        return codigoProducto;
    }

    public void setCodigoProducto(int codigoProducto) {
        this.codigoProducto = codigoProducto;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public double getPrecio() {
        return precio;
    }

    public void setPrecio(double precio) {
        this.precio = precio;
    }

}


4.2.2. Clase Venta

La clase Venta tiene la misma estructura de nuestra tabla Venta de nuestra base de datos, a continuación les comparto el código fuente de la clase.

package Modelo;

// @author hwong
import java.sql.Timestamp;

public class Venta {
    //Las columnas que tiene la tabla Venta

    private int codigoVenta;
    private String cliente;
    private Timestamp fecha;
    //Constructor de la clase sin parametros

    public Venta() {
    }
    //Constructor de la clase con parametros

    public Venta(int codigoVenta, String cliente, Timestamp fecha) {
        this.codigoVenta = codigoVenta;
        this.cliente = cliente;
        this.fecha = fecha;
    }
    //Metodos get y set de la clase

    public String getCliente() {
        return cliente;
    }

    public void setCliente(String cliente) {
        this.cliente = cliente;
    }

    public int getCodigoVenta() {
        return codigoVenta;
    }

    public void setCodigoVenta(int codigoVenta) {
        this.codigoVenta = codigoVenta;
    }

    public Timestamp getFecha() {
        return fecha;
    }

    public void setFecha(Timestamp fecha) {
        this.fecha = fecha;
    }

}

4.2.3. Clase DetalleVenta

La clase DetalleVenta tiene la misma estructura de nuestra tabla DetalleVenta de nuestra base de datos, a continuación les comparto el código fuente de la clase.

package Modelo;

// @author hwong
public class DetalleVenta {
    //Las columnas que tiene la tabla DetalleVenta

    private int codigoVenta;
    private int codigoProducto;
    private double cantidad;
    private double descuento;
    private Producto producto;
    private Venta venta;

    //Constructor sin parametros
    public DetalleVenta() {
    }
    //Constructor con parametros

    public DetalleVenta(int codigoVenta, int codigoProducto, double cantidad, double descuento) {
        this.codigoVenta = codigoVenta;
        this.codigoProducto = codigoProducto;
        this.cantidad = cantidad;
        this.descuento = descuento;
    }
    //Metodos Get y Set de la clase

    public double getCantidad() {
        return cantidad;
    }

    public void setCantidad(double cantidad) {
        this.cantidad = cantidad;
    }

    public int getCodigoProducto() {
        return codigoProducto;
    }

    public void setCodigoProducto(int codigoProducto) {
        this.codigoProducto = codigoProducto;
    }

    public int getCodigoVenta() {
        return codigoVenta;
    }

    public void setCodigoVenta(int codigoVenta) {
        this.codigoVenta = codigoVenta;
    }

    public double getDescuento() {
        return descuento;
    }

    public void setDescuento(double descuento) {
        this.descuento = descuento;
    }

    public Producto getProducto() {
        return producto;
    }

    public void setProducto(Producto producto) {
        this.producto = producto;
    }

    public Venta getVenta() {
        return venta;
    }

    public void setVenta(Venta venta) {
        this.venta = venta;
    }
}

4.2.4. Estructura final

Al finalizar de crear las clases deberiamos tener 3 clases tal como se muestra en el grafico siguiente

















4.3. Creando las clases para comunicar con la base de datos

4.3.1. Cargando el Driver

Para poder comunicar nuestro proyecto con MySQL 5.1. primero debemos de adicionar el driver a nuestro proyecto. Para eso hacemos clic derecho en nuestro proyecto y nos vamos a la opción que dice Properties y seleccionamos de ahí Libraries y presionamos el botón que dice Add Library y buscamos el que dice MySQL JDBC Driver

















4.3.2. Creando la clase Conexion

Esta clase es la que centraliza la conexión con nuestra base de datos que esta en MySQL nos va dar soporte para ciertos métodos que vamos a usar en nuestras demás clases

package Modelo;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;

//@author Henry Joe Wong Urquiza

public class Conexion {
    //La url con la cual nos conectariamos a la base de datos
    private static String url = "jdbc:mysql://localhost/bdtutorial";
    //El usuario de la base de datos
    private static String user = "root";
    //La clave del usuario de la base de datos
    private static String password = "clave";
    //Metodo para obtener la conexion con la base de datos
    public static synchronized Connection getConexion() {
        Connection cn = null;
        try {
            //Cargamos el driver y le decimos que vamos a usar
            //una conexion con mysql
            Class.forName("com.mysql.jdbc.Driver");
            //Obtenemos la conexion
            cn = DriverManager.getConnection(url, user, password);
        } catch (Exception e) {
            cn = null;
        } finally {
            return cn;
        }
    }
    //Metodo utilizado para cerrar el callablestatemente
    public static synchronized void cerrarCall(CallableStatement cl) {
        try{cl.close();}catch(Exception e){}
    }
    //Metodo utilizado para cerrar el resulset de datos
    public static synchronized void cerrarConexion(ResultSet rs) {
        try{rs.close();} catch (Exception e) {}
    }
    //Metodo utilizado para cerrar la conexion
    public static synchronized void cerrarConexion(Connection cn) {
        try{cn.close();} catch (Exception e) {}
    }
    //Metodo utilizado para deshacer los cambios en la base de datos
    public static synchronized void deshacerCambios(Connection cn) {
        try{cn.rollback();}catch (Exception e){}
    }
}


4.3.3. Creando la clase ProductoBD

Que se encargara de hacer las consultas o inserciones a nuestra tabla Producto


package Modelo;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;

// @autor Henry Joe Wong Uruqiza
// Archivo: ProductoBD.java
// Creado: 24FEBRERO2011 12:39:08 PM
public class ProductoBD {
    //Metodo utilizado para insertar un Producto a nuestra Base de datos

    public static synchronized boolean insertarProducto(Producto varproducto) {
        Connection cn = null;
        CallableStatement cl = null;
        boolean rpta = false;
        try {
            //Nombre del procedimiento almacenado y como espera tres parametros
            //le ponemos 3 interrogantes
            String call = "{CALL spI_producto(?,?,?)}";
            //Obtenemos la conexion
            cn = Conexion.getConexion();
            //Decimos que vamos a crear una transaccion
            cn.setAutoCommit(false);
            //Preparamos la sentecia
            cl = cn.prepareCall(call);
            //Como el codigo se autogenera y es del tipo OUT en el procedimiento
            //almacenado le decimos que es OUT y el del tipo Integer en Java
            cl.registerOutParameter(1, Types.INTEGER);
            //El siguiente parametro del procedimiento almacenado es el nombre
            cl.setString(2, varproducto.getNombre());
            //Y por ultimo el precio 
            cl.setDouble(3, varproducto.getPrecio());
            //Ejecutamos la sentencia y si nos devuelve el valor de 1 es porque
            //registro de forma correcta los datos
            rpta = cl.executeUpdate() == 1 ? true : false;
            if (rpta) {
                //Confirmamos la transaccion
                cn.commit();
            } else {
                //Negamos la transaccion
                Conexion.deshacerCambios(cn);
            }
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        } catch (SQLException e) {
            e.printStackTrace();
            Conexion.deshacerCambios(cn);
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        } catch (Exception e) {
            e.printStackTrace();
            Conexion.deshacerCambios(cn);
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        }
        return rpta;
    }

    //Metodo utilizado para insertar un Producto a nuestra Base de datos
    public static synchronized boolean actualizarProducto(Producto varproducto) {
        Connection cn = null;
        CallableStatement cl = null;
        boolean rpta = false;
        try {
            //Nombre del procedimiento almacenado y como espera tres parametros
            //le ponemos 3 interrogantes
            String call = "{CALL spU_producto(?,?,?)}";
            //Obtenemos la conexion
            cn = Conexion.getConexion();
            //Decimos que vamos a crear una transaccion
            cn.setAutoCommit(false);
            //Preparamos la sentecia
            cl = cn.prepareCall(call);
            //El primer parametro del procedimiento almacenado es el codigo
            cl.setInt(1, varproducto.getCodigoProducto());
            //El siguiente parametro del procedimiento almacenado es el nombre
            cl.setString(2, varproducto.getNombre());
            //Y por ultimo el precio
            cl.setDouble(3, varproducto.getPrecio());
            //Ejecutamos la sentencia y si nos devuelve el valor de 1 es porque
            //registro de forma correcta los datos
            rpta = cl.executeUpdate() == 1 ? true : false;
            if (rpta) {
                //Confirmamos la transaccion
                cn.commit();
            } else {
                //Negamos la transaccion
                Conexion.deshacerCambios(cn);
            }
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        } catch (SQLException e) {
            e.printStackTrace();
            Conexion.deshacerCambios(cn);
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        } catch (Exception e) {
            e.printStackTrace();
            Conexion.deshacerCambios(cn);
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        }
        return rpta;
    }
    //Metodo utilizado para obtener todos los productos de nuestra base de datos

    public static synchronized ArrayList<Producto> obtenerProducto() {
        //El array que contendra todos nuestros productos
        ArrayList<Producto> lista = new ArrayList<Producto>();
        Connection cn = null;
        CallableStatement cl = null;
        ResultSet rs = null;
        try {
            //Nombre del procedimiento almacenado
            String call = "{CALL spF_producto_all()}";
            cn = Conexion.getConexion();
            cl = cn.prepareCall(call);
            //La sentencia lo almacenamos en un resulset
            rs = cl.executeQuery();
            //Consultamos si hay datos para recorrerlo
            //e insertarlo en nuestro array
            while (rs.next()) {
                Producto p = new Producto();
                //Obtenemos los valores de la consulta y creamos
                //nuestro objeto producto
                p.setCodigoProducto(rs.getInt("codigoProducto"));
                p.setNombre(rs.getString("nombre"));
                p.setPrecio(rs.getDouble("precio"));
                //Lo adicionamos a nuestra lista
                lista.add(p);
            }
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        } catch (SQLException e) {
            e.printStackTrace();
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        } catch (Exception e) {
            e.printStackTrace();
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        }
        return lista;
    }

    //Metodo utilizado para obtener todos los productos de nuestra base de datos
    public static synchronized Producto obtenerProducto(int codigo) {
        Producto p = new Producto();
        Connection cn = null;
        CallableStatement cl = null;
        ResultSet rs = null;
        try {
            //Nombre del procedimiento almacenado
            String call = "{CALL spF_producto_one(?)}";
            cn = Conexion.getConexion();
            cl = cn.prepareCall(call);
            cl.setInt(1, codigo);
            //La sentencia lo almacenamos en un resulset
            rs = cl.executeQuery();
            //Consultamos si hay datos para recorrerlo
            //e insertarlo en nuestro array
            while (rs.next()) {
                //Obtenemos los valores de la consulta y creamos
                //nuestro objeto producto
                p.setCodigoProducto(rs.getInt("codigoProducto"));
                p.setNombre(rs.getString("nombre"));
                p.setPrecio(rs.getDouble("precio"));
            }
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        } catch (SQLException e) {
            e.printStackTrace();
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        } catch (Exception e) {
            e.printStackTrace();
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        }
        return p;
    }
}


4.3.4. Creando la clase DetalleVentaBD

Sirve para insertar un detalle de la venta, el metodo insertarDetalle espera obtener la conexion y la transaccion de la clase Venta. Debido a que esta ultima clase es la que inicia la transaccion con la base de datos y es la única encargada de confirmar o negar la transaccion

package Modelo;

// @autor Henry Joe Wong Uruqiza
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;

// Archivo: DetalleVentaBD.java
// Creado: 24FEBRERO2011 12:39:08 PM
public class DetalleVentaBD {

    //Metodo utilizado para insertar un Detalle de Venta a nuestra Base de datos
    //Obtenemos la conexion de Venta debido a que la clase Venta es la que inicia
    //la transaccion
    public static synchronized boolean insertarDetalleVenta(DetalleVenta varDetalle, Connection cn) {
        CallableStatement cl = null;
        boolean rpta = false;
        try {
            //Nombre del procedimiento almacenado y como espera tres parametros
            //le ponemos 3 interrogantes
            String call = "{CALL spI_detalleventa(?,?,?,?)}";
//Preparamos la sentecia
            cl = cn.prepareCall(call);
            //Codigo de la venta
            cl.setInt(1, varDetalle.getCodigoVenta());
            //Codigo del producto
            cl.setInt(2, varDetalle.getCodigoProducto());
            //La cantidad
            cl.setDouble(3, varDetalle.getCantidad());
            //El descuento
            cl.setDouble(4, varDetalle.getDescuento());
            //Ejecutamos la sentencia y si nos devuelve el valor de 1 es porque
            //registro de forma correcta los datos
            rpta = cl.executeUpdate() == 1 ? true : false;
            Conexion.cerrarCall(cl);
        } catch (SQLException e) {
            e.printStackTrace();
            Conexion.cerrarCall(cl);
        } catch (Exception e) {
            e.printStackTrace();
            Conexion.cerrarCall(cl);
        }
        return rpta;
    }
}

4.3.5. Creando la clase VentaBD

package Modelo;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;

// @autor Henry Joe Wong Uruqiza
// Archivo: VentaBD.java
// Creado: 24FEBRERO2011 12:39:08 PM
public class VentaBD {

    //Metodo utilizado para insertar una Venta a nuestra Base de datos
    public static synchronized boolean insertarVenta(Venta varventa, ArrayList<DetalleVenta> detalle) {

        Connection cn = null;
        CallableStatement cl = null;
        boolean rpta = false;
        try {
            //Nombre del procedimiento almacenado y como espera tres parametros
            //le ponemos 3 interrogantes
            String call = "{CALL spI_venta(?,?)}";
//Obtenemos la conexion
            cn = Conexion.getConexion();
            //Decimos que vamos a crear una transaccion
            cn.setAutoCommit(false);
            //Preparamos la sentecia
            cl = cn.prepareCall(call);
            //Como el codigo se autogenera y es del tipo OUT en el procedimiento
            //almacenado le decimos que es OUT y el del tipo Integer en Java
            cl.registerOutParameter(1, Types.INTEGER);
            //El siguiente parametro del procedimiento almacenado es el cliente
            cl.setString(2, varventa.getCliente());
            //Ejecutamos la sentencia y si nos devuelve el valor de 1 es porque
            //registro de forma correcta los datos
            rpta = cl.executeUpdate() == 1 ? true : false;
            //Codigo que se genero producto de la insercion ---> codigoVenta
            varventa.setCodigoVenta(cl.getInt(1));
            if (rpta) {
                for (DetalleVenta det : detalle) {
                    //Establecemos al detalle el codigo genero producto de la venta
                    det.setCodigoVenta(varventa.getCodigoVenta());
                    //Insertamos el detalle y le pasamos la conexion
                    rpta = DetalleVentaBD.insertarDetalleVenta(det, cn);
                    //Si nos devuelve false salimos del for
                    if (!rpta) {
                        break;
                    }
                }
                if (rpta) {
                    //Confirmamos la transaccion
                    cn.commit();
                } else {
                    //Negamos la transaccion
                    Conexion.deshacerCambios(cn);
                }
            } else {
                //Negamos la transaccion
                Conexion.deshacerCambios(cn);
            }
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        } catch (SQLException e) {
            e.printStackTrace();
            Conexion.deshacerCambios(cn);
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        } catch (Exception e) {
            e.printStackTrace();
            Conexion.deshacerCambios(cn);
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        }
        return rpta;
    }

    //Metodo utilizado para obtener todos las ventas de nuestra base de datos
    public static synchronized ArrayList<DetalleVenta> obtenerVentas() {
        //El array que contendra todos nuestros productos
        ArrayList<DetalleVenta> lista = new ArrayList<DetalleVenta>();
        Connection cn = null;
        CallableStatement cl = null;
        ResultSet rs = null;
        try {
            //Nombre del procedimiento almacenado
            String call = "{CALL spF_venta_All()}";
cn = Conexion.getConexion();
            cl = cn.prepareCall(call);
            //La sentencia lo almacenamos en un resulset
            rs = cl.executeQuery();
            //Consultamos si hay datos para recorrerlo
            //e insertarlo en nuestro array
            while (rs.next()) {
                Venta ven=new Venta();
                Producto pro=new Producto();
                DetalleVenta det=new DetalleVenta();
                ven.setCodigoVenta(rs.getInt("CodigoVenta"));
                ven.setCliente(rs.getString("Cliente"));
                ven.setFecha(rs.getTimestamp("Fecha"));
                pro.setCodigoProducto(rs.getInt("CodigoProducto"));
                pro.setNombre(rs.getString("Nombre"));
                pro.setPrecio(rs.getDouble("Precio"));
                det.setCantidad(rs.getDouble("Cantidad"));
                det.setDescuento(rs.getDouble("Parcial"));
                det.setVenta(ven);
                det.setProducto(pro);
                lista.add(det);
            }
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        } catch (SQLException e) {
            e.printStackTrace();
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        } catch (Exception e) {
            e.printStackTrace();
            Conexion.cerrarCall(cl);
            Conexion.cerrarConexion(cn);
        }
        return lista;
    }
}

4.4. Estructura final de todas las clases

14 comentarios:

HOla soy yesica otra vez

oye si no tengo la libreria de MySQL JDBC Driver para crear el programa que conectara la bd??



Saludos

lo puedes bajar de aca

http://dev.mysql.com/downloads/connector/j/5.0.html

y adjunto a tu proyecto

Gracias te agradesco :)

Gracias por el tutorial.
De donde puedo tener el proyecto completo.

La consulta por el tema del controlador , me dice que no lo encuentra en el servidor, queria saber porque me da ese error?

Muchas gracias

buenas tardes a todos, soy daniel

tengo una pregunta: ¿en el caso que no utilizara procedimientos almacenados tendría que cambiar la variable de tipo de dato CallableStatement por Statement y asi poder ejecutar insert o un select, o que me pude variar de este código ?

Exacto solo por eso lo cambias

muy interesante ... mi pregunta q libreria tendria q adjuntar si kiero realizarlo con sqlserver? .. porfavor responde

Acá puedes encontrar información al respecto

http://msdn.microsoft.com/en-us/library/ms378526.aspx

Excelente totorial, gracias por el aporte!!

Muchas Gracias por la ayuda desinteresada

GRACIAS POR LA AYUDA DESINTERESADA, GRACIAS POR COMPARTIR TU CONOCIMIENTOS

Muchas Gracias por la ayuda desinteresada

Gracias por compartir tus conocimientos para los que estamos entrando a esta nueva tecnologia nos ayuda mucho...

gracias por el codigo.. muy bueno para poder aprender