8 de marzo de 2013

Procedimientos Almacenados y Vistas en SQL-Java

Se creara una nueva aplicación en Java utilizando NetBeans 7.2.1 a la cual llamare EjemploSQL, una vez creada la aplicación se conectara a una base de datos en SQL Server utilizando ODBC como puente entre la aplicación y la base de datos, también se utilizaran procedimientos almacenados SQL para realizar las operaciones de agregar, modificar y eliminar los registros de un empleado sobre una tabla y una Vista en SQL para mostrar los datos de todos los empleados, los cuales se mostraran en un JTable desde un JForm, en caso se necesite reforzar la conexión Java-SQl vía ODBC les dejo el link en que se detallan los pasos: http://pabletoreto.blogspot.com/2013/03/conectar-java-sql-utilizando-odbc.html

En la aplicación EjemploSQL se crearan dos paquetes:
1. ConexionSQL: este paquete contendrá la clase Conexion con un método publico Conectar() que se conectara con la base de datos vía ODBC y entregara un objeto tipo Connection.
2. FormSQL: este paquete contendrá el formulario.

*****  Base de datos registro, diseño de la tabla empleado  *****


*****  Conexión a la base de datos registro en SQL(Package ConexionSQL)  *****
Trabajaremos sobre la clase Conexión.java para conectarnos a la base de datos registro en SQL, aquí está el código:

public class Conexion {
    static String user="";
    static String pass="";
    static String url="jdbc:odbc:SQLJava";

    public static Connection Conectar(){
        Connection cnn=null;
    try{
        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        cnn=DriverManager.getConnection(url, user, pass);
       }catch(ClassNotFoundException cnfex){
            System.out.println(cnfex.getMessage());
       }catch(SQLException sqlex){
            System.out.println(sqlex.getMessage());
       }catch(Exception ex){
            System.out.println(ex.getMessage());
      }
       return cnn;
    }}

*****  Diseño del JForm(Package FormSQL)  ***** 
A continuación presento el formulario JForm que se utilizara con las siguientes especificaciones:
El label Código Empleado utiliza el txtCodigo
El label Nombres utiliza el txtNombres
El label Cargo Empleado utiliza el txtCargo
El label Departamento utiliza el txtDpto
El label Jefe asignado utiliza el txtJefe
El botón IngresarDatos tiene definido el nombre BIngresar
El botón ModificarDatos tiene definido el nombre BModificar
El botón BorrarDatos tiene definido el nombre BEliminar
El JTable para mostrar los datos tiene definido el nombre tablita


*****  Procedimientos almacenados SQL Server-Java  *****
Presentare los procedimientos almacenados para los eventos de los botones Ingresar Datos, Modificar Datos y Eliminar Datos, para estas sencillas acciones no deberían utilizarse procedimientos almacenados a menos de querer tener una seguridad tan fuerte que termine siendo tosca e innecesaria, pero cada quien maneja su capa de datos como mejor le parezca, 

*****  Paquetes, librerías y variables necesarias(Package FormSQL)  *****
Estas son las librerías y variables que utilizare en este ejemplo

package FormSQL;
import java.sql.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.JOptionPane;
import ConexionSQL.Conexion;
public class FormSQL extends javax.swing.JFrame {
String Insertar= "{ call AgregarDatos(?,?,?,?,?) }";
String Modificar="{CALL ModificarDatos(?,?,?,?,?,?)}";
String Eliminar="{CALL EliminarDatos(?,?)}";
DefaultTableModel modelo;

    public FormSQL() {
     initComponents();
    CargarDatos();}


*****  Mostrando datos tabla empleado(Package FormSQL)  *****
Para mostrar los datos de la tabla empleado no se usara un procedimiento almacenado sino mas bien se construirá una vista en SQL, se usara la sentencia: select * from empleado, como sugerencia, se debe evitar en lo posible utilizar el * en sentencias select, pero en este ejemplo se utiliza sobre todo para mostrar la construcción y el uso de las vistas SQL en Java, ustedes pueden construir una vista más digna de su proyecto o acorde a sus necesidades, pero aquí vamos a los simple, este es el código de la vista :

SELECT  Codigo, Nombres, Cargo, Departamento, Jefe FROM dbo.empleado

La tabla se poblara con los datos cada vez que se inicie la aplicación y cada vez que se haga una acción sobre la base de datos, esto lo hará el método CargarDatos()

public void CargarDatos(){
            Connection cnn;   
            modelo= new DefaultTableModel(); 
        try{
            cnn=Conexion.Conectar();
            Statement smt=cnn.createStatement();
            ResultSet rs= smt.executeQuery("select * from seleccionardatos");
            ResultSetMetaData md=rs.getMetaData();
            int columnas= md.getColumnCount();
            for (int i = 1; i <= columnas; i++) {
            modelo.addColumn(md.getColumnLabel(i));}
            while(rs.next()){
            Object[] fila = new Object[columnas];
            for (int i = 0; i < columnas; i++) {fila[i]=rs.getObject(i+1);}
            modelo.addRow(fila);
            }tablita.setModel(modelo);
            cnn.close();
            }catch(SQLException sqlex){
            setTitle("Problema CargarDatos" +sqlex.getMessage());}}

*****  Ingresar datos a la tabla empleado(Package FormSQL)  *****
Primero mostrare el procedimiento almacenado en SQL para ingresar datos a la tabla empleado, ademas usare commit en los procedimientos almacenados para el caso de realizar mas acciones sobre diferentes tablas, que es el uso real que debe darse a los procedimientos almacenados.

USE registro
GO
IF OBJECT_ID('AgregarDatos','p')is not null
DROP PROCEDURE AgregarDatos
GO

CREATE PROCEDURE AgregarDatos
@nombres varchar(50),
@cargo varchar(50),
@departamento varchar(50),
@jefe varchar(50),
@mensaje varchar(100) output

AS
SET NOCOUNT ON
BEGIN TRY
BEGIN TRAN
INSERT INTO empleado VALUES(@nombres, @cargo, @departamento, @jefe)
COMMIT
SELECT @mensaje='Registro ingresado correctamente en Base de Datos !!!'
END TRY

BEGIN CATCH
ROLLBACK
SELECT @mensaje='Registro no ingresado en Base de Datos !!!'
END CATCH

Ahora presento el evento click del botón Ingresar Datos, este invoca al método IngresarDatos() y le envía los parámetros necesarios para realizar la operación de agregar datos sobre la tabla empleado

private void BIngresarActionPerformed(java.awt.event.ActionEvent evt) {                                         
        String Nombres=txtNombres.getText();
        String Dpto=txtDpto.getText();
        String Cargo=txtCargo.getText();
        String Jefe=txtJefe.getText();
        String resultado=AgregarDatos(Nombres, Cargo, Dpto, Jefe);
        setTitle(resultado);
        CargarDatos();}

y por último el método IngresarDatos() que se conecta con la base de datos, se utilizara este string: String Insertar="{CALL InsertarDatos(?,?,?,?,?)}"; para invocar al procedimiento almacenado InsertarDatos y se prepara la sentencia CallableStatement  para envíar los datos necesarios al procedimiento y agregar el registro correspondiente de la tabla empleados, al final refrescara el JTable con los nuevos datos de la tabla empleado.

public String AgregarDatos(String Nombres, String Cargo, String Dpto, String Jefe){
        Connection cnn;   
        String resultado;
        try{
           cnn=Conexion.Conectar(); 
           CallableStatement cmst;
           cmst = cnn.prepareCall(Insertar);
           cmst.setString(1,Nombres);
           cmst.setString(2,Cargo);
           cmst.setString(3,Dpto);
           cmst.setString(4, Jefe);
           cmst.registerOutParameter(5, java.sql.Types.VARCHAR,100);
           cmst.execute();
           resultado=cmst.getString(5);
           cnn.close();
        }catch(SQLException sqlex){
           resultado="No se realizo la operacion" +sqlex.getMessage();
        }catch(Exception ex){System.out.println(ex.getMessage());
           resultado="No se realizo la operacion" +ex.getMessage();
        }return resultado;}

*****  Modificar datos a la tabla empleado(Package FormSQL)  *****
Primero mostrare el procedimiento almacenado en SQL para modificar datos en la tabla empleadoademas usare commit en los procedimientos almacenados para el caso de realizar mas acciones sobre diferentes tablas, que es el uso real que debe darse a los procedimientos almacenados.

USE registro
GO
if OBJECT_ID('ModificarDatos','p') is not null
DROP PROC ModificarDatos
GO

CREATE PROC ModificarDatos
@codigo int,
@nombres varchar(50),
@cargo varchar(50),
@departamento varchar(50),
@jefe varchar(50),
@mensaje varchar(100) output

AS
SET NOCOUNT ON
IF exists (select * from empleado where Codigo=@codigo)
BEGIN TRY
BEGIN TRAN
UPDATE empleado SET Nombres=@nombres, Cargo=@cargo,Departamento=@departamento, Jefe=@jefe WHERE Codigo=@codigo
COMMIT
SET @mensaje='El registro fue actualizado correctamente !!!'
END TRY

BEGIN CATCH
ROLLBACK
SET @mensaje='El registro no fue actualizado !!!'
END CATCH
ELSE
BEGIN
SET @mensaje='El registro no existe en la base de datos !!!'
END

Ahora presento el evento click del botón Modificar Datos, este invoca al método ModificarDatos() y le envía los parámetros necesarios para realizar la operación de modificación sobre la tabla empleado

private void BModificarActionPerformed(java.awt.event.ActionEvent evt) {                                           
        int Codigo=Integer.parseInt(txtCodigo.getText());
        String Nombres=txtNombres.getText();
        String Dpto=txtDpto.getText();
        String Cargo=txtCargo.getText();
        String Jefe=txtJefe.getText();
        String resultado=ModificarDatos(Codigo,Nombres, Cargo, Dpto, Jefe);
        setTitle(resultado);
        CargarDatos();}

y por ultimo el método ModificarDatos() que se conecta con la base de datos, se utilizara este string: String Modificar="{CALL ModificarDatos(?,?,?,?,?,?)}"; para invocar al procedimiento almacenado ModificarDatos y se prepara la sentencia CallableStatement  para envíar los datos necesarios al procedimiento y modificar el registro correspondiente de la tabla empleados, al final refrescara el JTable con los nuevos datos de la tabla empleado.

public String ModificarDatos(int Codigo,String Nombres, String Cargo, String Dpto, String Jefe){
            Connection cnn;   
            String resultado;
        try{
           cnn=Conexion.Conectar();
           CallableStatement cmst= cnn.prepareCall(Modificar);
           cmst.setInt(1, Codigo);
           cmst.setString(2,Nombres);
           cmst.setString(3,Cargo);
           cmst.setString(4,Dpto);
           cmst.setString(5, Jefe);
           cmst.registerOutParameter(6, java.sql.Types.VARCHAR,100);
           cmst.execute();
           resultado=cmst.getString(6);
           cnn.close();  
        }catch(SQLException sqlex){
           resultado="No se realizo la operacion" +sqlex.getMessage();
        }catch(Exception ex){System.out.println(ex.getMessage());
           resultado="No se realizo la operacion" +ex.getMessage();
        }return resultado;}

*****  Eliminar datos de la tabla empleado(Package Formulario)  *****
Primero mostrare el procedimiento almacenado en SQL para eliminar datos en la tabla empleadoademas usare commit en los procedimientos almacenados para el caso de realizar mas acciones sobre diferentes tablas, que es el uso real que debe darse a los procedimientos almacenados.

USE registro
GO
IF OBJECT_ID('EliminarDatos','p')is not null
DROP PROC EliminarDatos
GO

CREATE PROCEDURE EliminarDatos
@codigo int,
@mensaje varchar(100) output

AS
SET NOCOUNT ON
IF EXISTS (select * from empleado where Codigo=@codigo)
BEGIN TRY
BEGIN TRANSACTION
DELETE FROM empleado WHERE Codigo=@codigo
COMMIT
SELECT @mensaje='Registro eliminado correctamente de Base de Datos !!!'
END TRY

BEGIN CATCH
ROLLBACK
set @mensaje='Registro no fue eliminado de la Base de Datos !!!'
END CATCH
ELSE
BEGIN
SET @mensaje='Registro no se puede eliminar pues no existe !!!'
END

Ahora el evento click del botón Eliminar Datos, este invoca al método EliminarDatos() y le envía los parámetros necesarios para realizar la operación de eliminar un registro de la tabla empleado

private void BEliminarActionPerformed(java.awt.event.ActionEvent evt) {                                          
        int Codigo=Integer.parseInt(txtCodigo.getText());
        String resultado=EliminarDatos(Codigo);
        setTitle(resultado);
        CargarDatos();}

y por ultimo el método EliminarDatos() que se conecta con la base de datos, se utilizara este string: String Eliminar="CALL BorrarDatos(?,?)"; para invocar al procedimiento almacenado BorrarDatos y se prepara la sentencia CallableStatement   para envíar los datos necesarios al procedimiento y eliminar el registro correspondiente de la tabla empleados, al final refrescara el JTable con los nuevos datos de la tabla empleado.

public String EliminarDatos(int Codigo){
        Connection cnn;   
            String resultado;
        try{
           cnn=Conexion.Conectar();
           CallableStatement cmst= cnn.prepareCall(Eliminar);
           cmst.setInt(1, Codigo);
           cmst.registerOutParameter(2, java.sql.Types.VARCHAR,100);
           cmst.execute();
           resultado=cmst.getString(2);
           cnn.close();
        }catch(SQLException sqlex){
           resultado="No se realizo la operacion" +sqlex.getMessage();
        }catch(Exception ex){System.out.println(ex.getMessage());
           resultado="No se realizo la operacion" +ex.getMessage();
        }return resultado;}