crud de tabla producto con swing -...

35
UNIVERSIDAD DE EL SALVADOR ESCUELA DE INGENIERIA DE SISTEMAS INFORMATICOS PROGRAMACION III CRUD de tabla PRODUCTO con Swing

Upload: others

Post on 06-Apr-2020

12 views

Category:

Documents


0 download

TRANSCRIPT

UNIVERSIDAD DE EL SALVADOR

ESCUELA DE INGENIERIA DE SISTEMAS INFORMATICOS

PROGRAMACION III

CRUD de tabla PRODUCTO con Swing

1

Contenido

Diagrama Fiacutesico de Base de Datos Para un Sistema de Ventas Baacutesico 2

Conectarse a su usuario carnet que fue creado en la guiacutea 05 2

Crear Tablas de la base de datos de Ventas 4

Verificar que las tablas estaacuten creadas 4

Antildeadir registros desde un archivo 4

Caso de uso Mantenimiento de productos 6

Programacioacuten de Mantenimiento de productos 8

Modelo para registrar el producto en jFrame 11

Modificar el jFrame(Definir la instancia de ProductoTableModel) 13

Conexioacuten a Base de Datos 15

Programacioacuten de los botones de Accioacuten 21

Ejercicio Adicional 30

Anexo 1 30

2

Diagrama Fiacutesico de Base de Datos Para un Sistema de Ventas Baacutesico

Nota Se creara toda la estructura aunque solo utilizaremos dos tablas(Producto y Cliente)

Conectarse a su usuario carnet que fue creado en la guiacutea 05

Entre a su conexioacuten o cree una nueva con los paraacutemetros que se muestran

Nota Si tiene problemas para entrar o no ha creado su usuario carnet remitase al Anexo 2 (Instalacioacuten)

numeral 2 que se encuentra en la guiacutea 05 en donde se detallan los pasos para entrar al administrador y crearlo

3

Renombrar Tabla Producto (creado en la Guiacutea 5 si no la realizo omita este paso y pase a crear las

tablas de la base de datos(siguiente paacutegina) )

Para crear la base de datos de esta guiacutea existe la tabla Producto que posee el mismo nombre de la hecha el laboratorio 5 por

lo que la deberaacute renombrar o eliminar(Clic derecho drop)

Para renombrar Presione clic derecho luego clic en properties

Digite un nombre como productoold u otro que sea diferente a producto por ejemplo productoold

4

Crear Tablas de la base de datos de Ventas

Presione clic derecho en carnet luego clic en CREATE Script borre el coacutedigo que estaacute y agreacuteguele el coacutedigo que estaacute en el

anexo 1 luego presione clic en execute PgScript

Verificar que las tablas estaacuten creadas

Si no aparecen presione clic derecho clic en refresh sobre la base de datos carnet

Antildeadir registros desde un archivo

Descargue el archivo de datos desde el aula virtual

httpaulafiauesedusvmodresourceviewphpid=49943

Presione clic derecho sobre la tabla producto luego clic en import

5

Luego configure la ventana de importacioacuten como se muestra

Presione clic en import y espere a que termine la barra de progreso luego presione Done

6

Caso de uso Mantenimiento de productos

Nombre Mantenimiento de productos

Autor PRN315

Descripcioacuten Permite guardar modificar y eliminar productos de la base de datos

Actores Administrador

Precondiciones

Flujo normal de los eventos

1 El Administrador inicia el programa

2 El sistema muestra la interfaz de mantenimiento de productos con todos los productos encontrados en la base

de datos a traveacutes de una consulta inicial

3 El Administrador desea realizar una buacutesqueda de archivos se realiza la seccioacuten Buscar

4 El Administrador desea modificar uno de los producto se realiza la seccioacuten Actualizar

5 El Administrador desea ingresar un producto nuevo se realiza la seccioacuten Ingresar nuevo

6 El Administrador desea eliminar un producto se realiza la seccioacuten Eliminar

Flujos alternativos

Postcondiciones

7

Seccioacuten Buscar

1 El Administrador ingresa ellos criterios de buacutesqueda (coacutedigo y nombre) y presiona el botoacuten Buscar

2 El sistema realiza una consulta a la base de datos a partir de los criterios especificados y actualiza la tabla de

datos con los resultados encontrados

Seccioacuten Actualizar

1 El Administrador elige uno de los productos mostrados en la tabla haciendo doble clic el producto que desea

modificar

2 El sistema actualiza los controles de mantenimiento con los datos del producto seleccionado

3 El Administrador modifica los datos del producto y presiona el botoacuten actualizar

4 El registro fue actualizado satisfactoriamente El sistema actualiza el registro en la tabla

Cursos alternativos

4 Ocurrioacute un error al modificar el registro El sistema muestra un mensaje de error

Seccioacuten Ingresar nuevo

1 Los controles del formulario se encuentra vaciacuteos El Administrador llena los campos del formulario Coacutedigo

Nombre Cantidad en existencia y Precio unitario y presiona el botoacuten Guardar

2 El sistema almacena el registro en la base de datos y agrega el producto al final de la tabla

Cursos alternativos

1 Los controles tienen informacioacuten de un producto previamente seleccionado El Administrador presiona el botoacuten

Nuevo

12 El sistema limpia los controles

2 Ocurrioacute un error al guardar el registro El mensaje muestra un mensaje de error

8

Programacioacuten de Mantenimiento de productos

Haga un proyecto netbeans con el nombre CarnetLab06ejem01

Agregue un formulario jframe llamado MantenimientoProductos

9

Configuacuterelo como principal de ejecucioacuten

Disentildee la interfaz de usuario que corresponde al caso de uso descrito esta deberaacute tener la siguiente forma

Para los campos Cantidad en existencia y Precio unitario puede utilizar controles de tipo JFormattedTextField

Nota los dos recuadros negros son jPanel

10

Utilice los siguientes nombres de los controles

NOMBRE TIPO DE

COMPONENTE

DESCRIPCION

btnBuscar JButton El botoacuten que dispararaacute el evento clic que generaraacute la buacutesqueda de los

productos en la base de datos que correspondan a los criterios ingresados

btnElimina JButton El botoacuten que dispararaacute el evento clic que generaraacute la eliminacioacuten de los

productos seleccionados en la tabla

btnGuardar JButton El botoacuten que dispararaacute el evento clic que guardaraacute los datos ingresados en

los campos de la seccioacuten Mantenimiento

btnNuevo JButton El botoacuten que limpiaraacute el control del coacutedigo del producto cuando ya se haya

seleccionado un producto de la tabla

lBusqCod JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el coacutedigo del

producto

lBusqNombre JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el nombre del

producto

lCodigo JLabel Label (etiqueta) que corresponde al campo Coacutedigo del producto

lNombre JLabel Label (etiqueta) que corresponde al campo Nombre del producto

lCantidadExist JLabel Label (etiqueta) que corresponde al campo Cantidad en existencia del

producto

lPrecioUnit JLabel Label (etiqueta) que corresponde al Precio unitario del producto

tablaProductos JTable Tabla de producto

txtBusqCodigo JTextField Cuadro de texto para el criterio de buacutesqueda Coacutedigo del producto

txtBusqNombre JTextField Cuadro de texto para el criterio de buacutesqueda Nombre del producto

txtCodigo JTextField Cuadro de texto para la captura del Coacutedigo del producto

txtNombre JTextField Cuadro de texto para la captura del Nombre del producto

txtCantidadExistencia

JFormattedTextField Cuadro de texto con formato para la captura de la Cantidad en existencia

del producto

txtPrecioUnitario JFormattedTextField Cuadro de texto con formato para la captura del Precio unitario del

producto

Es opcional que le defina nombre

Para cada objeto presione clic derecho clic en Cambiar nombre de variable

11

Luego digite el nombre nuevo y presione aceptar

Modelo para registrar el producto en jFrame

Para el modelo de datos de la tabla se tiene una clase ProductoTableModel que usa la clase Producto

Dentro del proyecto Netbeans crearemos primero las clases que daraacuten soporte al modelo de datos de la tabla

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

1

Contenido

Diagrama Fiacutesico de Base de Datos Para un Sistema de Ventas Baacutesico 2

Conectarse a su usuario carnet que fue creado en la guiacutea 05 2

Crear Tablas de la base de datos de Ventas 4

Verificar que las tablas estaacuten creadas 4

Antildeadir registros desde un archivo 4

Caso de uso Mantenimiento de productos 6

Programacioacuten de Mantenimiento de productos 8

Modelo para registrar el producto en jFrame 11

Modificar el jFrame(Definir la instancia de ProductoTableModel) 13

Conexioacuten a Base de Datos 15

Programacioacuten de los botones de Accioacuten 21

Ejercicio Adicional 30

Anexo 1 30

2

Diagrama Fiacutesico de Base de Datos Para un Sistema de Ventas Baacutesico

Nota Se creara toda la estructura aunque solo utilizaremos dos tablas(Producto y Cliente)

Conectarse a su usuario carnet que fue creado en la guiacutea 05

Entre a su conexioacuten o cree una nueva con los paraacutemetros que se muestran

Nota Si tiene problemas para entrar o no ha creado su usuario carnet remitase al Anexo 2 (Instalacioacuten)

numeral 2 que se encuentra en la guiacutea 05 en donde se detallan los pasos para entrar al administrador y crearlo

3

Renombrar Tabla Producto (creado en la Guiacutea 5 si no la realizo omita este paso y pase a crear las

tablas de la base de datos(siguiente paacutegina) )

Para crear la base de datos de esta guiacutea existe la tabla Producto que posee el mismo nombre de la hecha el laboratorio 5 por

lo que la deberaacute renombrar o eliminar(Clic derecho drop)

Para renombrar Presione clic derecho luego clic en properties

Digite un nombre como productoold u otro que sea diferente a producto por ejemplo productoold

4

Crear Tablas de la base de datos de Ventas

Presione clic derecho en carnet luego clic en CREATE Script borre el coacutedigo que estaacute y agreacuteguele el coacutedigo que estaacute en el

anexo 1 luego presione clic en execute PgScript

Verificar que las tablas estaacuten creadas

Si no aparecen presione clic derecho clic en refresh sobre la base de datos carnet

Antildeadir registros desde un archivo

Descargue el archivo de datos desde el aula virtual

httpaulafiauesedusvmodresourceviewphpid=49943

Presione clic derecho sobre la tabla producto luego clic en import

5

Luego configure la ventana de importacioacuten como se muestra

Presione clic en import y espere a que termine la barra de progreso luego presione Done

6

Caso de uso Mantenimiento de productos

Nombre Mantenimiento de productos

Autor PRN315

Descripcioacuten Permite guardar modificar y eliminar productos de la base de datos

Actores Administrador

Precondiciones

Flujo normal de los eventos

1 El Administrador inicia el programa

2 El sistema muestra la interfaz de mantenimiento de productos con todos los productos encontrados en la base

de datos a traveacutes de una consulta inicial

3 El Administrador desea realizar una buacutesqueda de archivos se realiza la seccioacuten Buscar

4 El Administrador desea modificar uno de los producto se realiza la seccioacuten Actualizar

5 El Administrador desea ingresar un producto nuevo se realiza la seccioacuten Ingresar nuevo

6 El Administrador desea eliminar un producto se realiza la seccioacuten Eliminar

Flujos alternativos

Postcondiciones

7

Seccioacuten Buscar

1 El Administrador ingresa ellos criterios de buacutesqueda (coacutedigo y nombre) y presiona el botoacuten Buscar

2 El sistema realiza una consulta a la base de datos a partir de los criterios especificados y actualiza la tabla de

datos con los resultados encontrados

Seccioacuten Actualizar

1 El Administrador elige uno de los productos mostrados en la tabla haciendo doble clic el producto que desea

modificar

2 El sistema actualiza los controles de mantenimiento con los datos del producto seleccionado

3 El Administrador modifica los datos del producto y presiona el botoacuten actualizar

4 El registro fue actualizado satisfactoriamente El sistema actualiza el registro en la tabla

Cursos alternativos

4 Ocurrioacute un error al modificar el registro El sistema muestra un mensaje de error

Seccioacuten Ingresar nuevo

1 Los controles del formulario se encuentra vaciacuteos El Administrador llena los campos del formulario Coacutedigo

Nombre Cantidad en existencia y Precio unitario y presiona el botoacuten Guardar

2 El sistema almacena el registro en la base de datos y agrega el producto al final de la tabla

Cursos alternativos

1 Los controles tienen informacioacuten de un producto previamente seleccionado El Administrador presiona el botoacuten

Nuevo

12 El sistema limpia los controles

2 Ocurrioacute un error al guardar el registro El mensaje muestra un mensaje de error

8

Programacioacuten de Mantenimiento de productos

Haga un proyecto netbeans con el nombre CarnetLab06ejem01

Agregue un formulario jframe llamado MantenimientoProductos

9

Configuacuterelo como principal de ejecucioacuten

Disentildee la interfaz de usuario que corresponde al caso de uso descrito esta deberaacute tener la siguiente forma

Para los campos Cantidad en existencia y Precio unitario puede utilizar controles de tipo JFormattedTextField

Nota los dos recuadros negros son jPanel

10

Utilice los siguientes nombres de los controles

NOMBRE TIPO DE

COMPONENTE

DESCRIPCION

btnBuscar JButton El botoacuten que dispararaacute el evento clic que generaraacute la buacutesqueda de los

productos en la base de datos que correspondan a los criterios ingresados

btnElimina JButton El botoacuten que dispararaacute el evento clic que generaraacute la eliminacioacuten de los

productos seleccionados en la tabla

btnGuardar JButton El botoacuten que dispararaacute el evento clic que guardaraacute los datos ingresados en

los campos de la seccioacuten Mantenimiento

btnNuevo JButton El botoacuten que limpiaraacute el control del coacutedigo del producto cuando ya se haya

seleccionado un producto de la tabla

lBusqCod JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el coacutedigo del

producto

lBusqNombre JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el nombre del

producto

lCodigo JLabel Label (etiqueta) que corresponde al campo Coacutedigo del producto

lNombre JLabel Label (etiqueta) que corresponde al campo Nombre del producto

lCantidadExist JLabel Label (etiqueta) que corresponde al campo Cantidad en existencia del

producto

lPrecioUnit JLabel Label (etiqueta) que corresponde al Precio unitario del producto

tablaProductos JTable Tabla de producto

txtBusqCodigo JTextField Cuadro de texto para el criterio de buacutesqueda Coacutedigo del producto

txtBusqNombre JTextField Cuadro de texto para el criterio de buacutesqueda Nombre del producto

txtCodigo JTextField Cuadro de texto para la captura del Coacutedigo del producto

txtNombre JTextField Cuadro de texto para la captura del Nombre del producto

txtCantidadExistencia

JFormattedTextField Cuadro de texto con formato para la captura de la Cantidad en existencia

del producto

txtPrecioUnitario JFormattedTextField Cuadro de texto con formato para la captura del Precio unitario del

producto

Es opcional que le defina nombre

Para cada objeto presione clic derecho clic en Cambiar nombre de variable

11

Luego digite el nombre nuevo y presione aceptar

Modelo para registrar el producto en jFrame

Para el modelo de datos de la tabla se tiene una clase ProductoTableModel que usa la clase Producto

Dentro del proyecto Netbeans crearemos primero las clases que daraacuten soporte al modelo de datos de la tabla

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

2

Diagrama Fiacutesico de Base de Datos Para un Sistema de Ventas Baacutesico

Nota Se creara toda la estructura aunque solo utilizaremos dos tablas(Producto y Cliente)

Conectarse a su usuario carnet que fue creado en la guiacutea 05

Entre a su conexioacuten o cree una nueva con los paraacutemetros que se muestran

Nota Si tiene problemas para entrar o no ha creado su usuario carnet remitase al Anexo 2 (Instalacioacuten)

numeral 2 que se encuentra en la guiacutea 05 en donde se detallan los pasos para entrar al administrador y crearlo

3

Renombrar Tabla Producto (creado en la Guiacutea 5 si no la realizo omita este paso y pase a crear las

tablas de la base de datos(siguiente paacutegina) )

Para crear la base de datos de esta guiacutea existe la tabla Producto que posee el mismo nombre de la hecha el laboratorio 5 por

lo que la deberaacute renombrar o eliminar(Clic derecho drop)

Para renombrar Presione clic derecho luego clic en properties

Digite un nombre como productoold u otro que sea diferente a producto por ejemplo productoold

4

Crear Tablas de la base de datos de Ventas

Presione clic derecho en carnet luego clic en CREATE Script borre el coacutedigo que estaacute y agreacuteguele el coacutedigo que estaacute en el

anexo 1 luego presione clic en execute PgScript

Verificar que las tablas estaacuten creadas

Si no aparecen presione clic derecho clic en refresh sobre la base de datos carnet

Antildeadir registros desde un archivo

Descargue el archivo de datos desde el aula virtual

httpaulafiauesedusvmodresourceviewphpid=49943

Presione clic derecho sobre la tabla producto luego clic en import

5

Luego configure la ventana de importacioacuten como se muestra

Presione clic en import y espere a que termine la barra de progreso luego presione Done

6

Caso de uso Mantenimiento de productos

Nombre Mantenimiento de productos

Autor PRN315

Descripcioacuten Permite guardar modificar y eliminar productos de la base de datos

Actores Administrador

Precondiciones

Flujo normal de los eventos

1 El Administrador inicia el programa

2 El sistema muestra la interfaz de mantenimiento de productos con todos los productos encontrados en la base

de datos a traveacutes de una consulta inicial

3 El Administrador desea realizar una buacutesqueda de archivos se realiza la seccioacuten Buscar

4 El Administrador desea modificar uno de los producto se realiza la seccioacuten Actualizar

5 El Administrador desea ingresar un producto nuevo se realiza la seccioacuten Ingresar nuevo

6 El Administrador desea eliminar un producto se realiza la seccioacuten Eliminar

Flujos alternativos

Postcondiciones

7

Seccioacuten Buscar

1 El Administrador ingresa ellos criterios de buacutesqueda (coacutedigo y nombre) y presiona el botoacuten Buscar

2 El sistema realiza una consulta a la base de datos a partir de los criterios especificados y actualiza la tabla de

datos con los resultados encontrados

Seccioacuten Actualizar

1 El Administrador elige uno de los productos mostrados en la tabla haciendo doble clic el producto que desea

modificar

2 El sistema actualiza los controles de mantenimiento con los datos del producto seleccionado

3 El Administrador modifica los datos del producto y presiona el botoacuten actualizar

4 El registro fue actualizado satisfactoriamente El sistema actualiza el registro en la tabla

Cursos alternativos

4 Ocurrioacute un error al modificar el registro El sistema muestra un mensaje de error

Seccioacuten Ingresar nuevo

1 Los controles del formulario se encuentra vaciacuteos El Administrador llena los campos del formulario Coacutedigo

Nombre Cantidad en existencia y Precio unitario y presiona el botoacuten Guardar

2 El sistema almacena el registro en la base de datos y agrega el producto al final de la tabla

Cursos alternativos

1 Los controles tienen informacioacuten de un producto previamente seleccionado El Administrador presiona el botoacuten

Nuevo

12 El sistema limpia los controles

2 Ocurrioacute un error al guardar el registro El mensaje muestra un mensaje de error

8

Programacioacuten de Mantenimiento de productos

Haga un proyecto netbeans con el nombre CarnetLab06ejem01

Agregue un formulario jframe llamado MantenimientoProductos

9

Configuacuterelo como principal de ejecucioacuten

Disentildee la interfaz de usuario que corresponde al caso de uso descrito esta deberaacute tener la siguiente forma

Para los campos Cantidad en existencia y Precio unitario puede utilizar controles de tipo JFormattedTextField

Nota los dos recuadros negros son jPanel

10

Utilice los siguientes nombres de los controles

NOMBRE TIPO DE

COMPONENTE

DESCRIPCION

btnBuscar JButton El botoacuten que dispararaacute el evento clic que generaraacute la buacutesqueda de los

productos en la base de datos que correspondan a los criterios ingresados

btnElimina JButton El botoacuten que dispararaacute el evento clic que generaraacute la eliminacioacuten de los

productos seleccionados en la tabla

btnGuardar JButton El botoacuten que dispararaacute el evento clic que guardaraacute los datos ingresados en

los campos de la seccioacuten Mantenimiento

btnNuevo JButton El botoacuten que limpiaraacute el control del coacutedigo del producto cuando ya se haya

seleccionado un producto de la tabla

lBusqCod JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el coacutedigo del

producto

lBusqNombre JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el nombre del

producto

lCodigo JLabel Label (etiqueta) que corresponde al campo Coacutedigo del producto

lNombre JLabel Label (etiqueta) que corresponde al campo Nombre del producto

lCantidadExist JLabel Label (etiqueta) que corresponde al campo Cantidad en existencia del

producto

lPrecioUnit JLabel Label (etiqueta) que corresponde al Precio unitario del producto

tablaProductos JTable Tabla de producto

txtBusqCodigo JTextField Cuadro de texto para el criterio de buacutesqueda Coacutedigo del producto

txtBusqNombre JTextField Cuadro de texto para el criterio de buacutesqueda Nombre del producto

txtCodigo JTextField Cuadro de texto para la captura del Coacutedigo del producto

txtNombre JTextField Cuadro de texto para la captura del Nombre del producto

txtCantidadExistencia

JFormattedTextField Cuadro de texto con formato para la captura de la Cantidad en existencia

del producto

txtPrecioUnitario JFormattedTextField Cuadro de texto con formato para la captura del Precio unitario del

producto

Es opcional que le defina nombre

Para cada objeto presione clic derecho clic en Cambiar nombre de variable

11

Luego digite el nombre nuevo y presione aceptar

Modelo para registrar el producto en jFrame

Para el modelo de datos de la tabla se tiene una clase ProductoTableModel que usa la clase Producto

Dentro del proyecto Netbeans crearemos primero las clases que daraacuten soporte al modelo de datos de la tabla

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

3

Renombrar Tabla Producto (creado en la Guiacutea 5 si no la realizo omita este paso y pase a crear las

tablas de la base de datos(siguiente paacutegina) )

Para crear la base de datos de esta guiacutea existe la tabla Producto que posee el mismo nombre de la hecha el laboratorio 5 por

lo que la deberaacute renombrar o eliminar(Clic derecho drop)

Para renombrar Presione clic derecho luego clic en properties

Digite un nombre como productoold u otro que sea diferente a producto por ejemplo productoold

4

Crear Tablas de la base de datos de Ventas

Presione clic derecho en carnet luego clic en CREATE Script borre el coacutedigo que estaacute y agreacuteguele el coacutedigo que estaacute en el

anexo 1 luego presione clic en execute PgScript

Verificar que las tablas estaacuten creadas

Si no aparecen presione clic derecho clic en refresh sobre la base de datos carnet

Antildeadir registros desde un archivo

Descargue el archivo de datos desde el aula virtual

httpaulafiauesedusvmodresourceviewphpid=49943

Presione clic derecho sobre la tabla producto luego clic en import

5

Luego configure la ventana de importacioacuten como se muestra

Presione clic en import y espere a que termine la barra de progreso luego presione Done

6

Caso de uso Mantenimiento de productos

Nombre Mantenimiento de productos

Autor PRN315

Descripcioacuten Permite guardar modificar y eliminar productos de la base de datos

Actores Administrador

Precondiciones

Flujo normal de los eventos

1 El Administrador inicia el programa

2 El sistema muestra la interfaz de mantenimiento de productos con todos los productos encontrados en la base

de datos a traveacutes de una consulta inicial

3 El Administrador desea realizar una buacutesqueda de archivos se realiza la seccioacuten Buscar

4 El Administrador desea modificar uno de los producto se realiza la seccioacuten Actualizar

5 El Administrador desea ingresar un producto nuevo se realiza la seccioacuten Ingresar nuevo

6 El Administrador desea eliminar un producto se realiza la seccioacuten Eliminar

Flujos alternativos

Postcondiciones

7

Seccioacuten Buscar

1 El Administrador ingresa ellos criterios de buacutesqueda (coacutedigo y nombre) y presiona el botoacuten Buscar

2 El sistema realiza una consulta a la base de datos a partir de los criterios especificados y actualiza la tabla de

datos con los resultados encontrados

Seccioacuten Actualizar

1 El Administrador elige uno de los productos mostrados en la tabla haciendo doble clic el producto que desea

modificar

2 El sistema actualiza los controles de mantenimiento con los datos del producto seleccionado

3 El Administrador modifica los datos del producto y presiona el botoacuten actualizar

4 El registro fue actualizado satisfactoriamente El sistema actualiza el registro en la tabla

Cursos alternativos

4 Ocurrioacute un error al modificar el registro El sistema muestra un mensaje de error

Seccioacuten Ingresar nuevo

1 Los controles del formulario se encuentra vaciacuteos El Administrador llena los campos del formulario Coacutedigo

Nombre Cantidad en existencia y Precio unitario y presiona el botoacuten Guardar

2 El sistema almacena el registro en la base de datos y agrega el producto al final de la tabla

Cursos alternativos

1 Los controles tienen informacioacuten de un producto previamente seleccionado El Administrador presiona el botoacuten

Nuevo

12 El sistema limpia los controles

2 Ocurrioacute un error al guardar el registro El mensaje muestra un mensaje de error

8

Programacioacuten de Mantenimiento de productos

Haga un proyecto netbeans con el nombre CarnetLab06ejem01

Agregue un formulario jframe llamado MantenimientoProductos

9

Configuacuterelo como principal de ejecucioacuten

Disentildee la interfaz de usuario que corresponde al caso de uso descrito esta deberaacute tener la siguiente forma

Para los campos Cantidad en existencia y Precio unitario puede utilizar controles de tipo JFormattedTextField

Nota los dos recuadros negros son jPanel

10

Utilice los siguientes nombres de los controles

NOMBRE TIPO DE

COMPONENTE

DESCRIPCION

btnBuscar JButton El botoacuten que dispararaacute el evento clic que generaraacute la buacutesqueda de los

productos en la base de datos que correspondan a los criterios ingresados

btnElimina JButton El botoacuten que dispararaacute el evento clic que generaraacute la eliminacioacuten de los

productos seleccionados en la tabla

btnGuardar JButton El botoacuten que dispararaacute el evento clic que guardaraacute los datos ingresados en

los campos de la seccioacuten Mantenimiento

btnNuevo JButton El botoacuten que limpiaraacute el control del coacutedigo del producto cuando ya se haya

seleccionado un producto de la tabla

lBusqCod JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el coacutedigo del

producto

lBusqNombre JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el nombre del

producto

lCodigo JLabel Label (etiqueta) que corresponde al campo Coacutedigo del producto

lNombre JLabel Label (etiqueta) que corresponde al campo Nombre del producto

lCantidadExist JLabel Label (etiqueta) que corresponde al campo Cantidad en existencia del

producto

lPrecioUnit JLabel Label (etiqueta) que corresponde al Precio unitario del producto

tablaProductos JTable Tabla de producto

txtBusqCodigo JTextField Cuadro de texto para el criterio de buacutesqueda Coacutedigo del producto

txtBusqNombre JTextField Cuadro de texto para el criterio de buacutesqueda Nombre del producto

txtCodigo JTextField Cuadro de texto para la captura del Coacutedigo del producto

txtNombre JTextField Cuadro de texto para la captura del Nombre del producto

txtCantidadExistencia

JFormattedTextField Cuadro de texto con formato para la captura de la Cantidad en existencia

del producto

txtPrecioUnitario JFormattedTextField Cuadro de texto con formato para la captura del Precio unitario del

producto

Es opcional que le defina nombre

Para cada objeto presione clic derecho clic en Cambiar nombre de variable

11

Luego digite el nombre nuevo y presione aceptar

Modelo para registrar el producto en jFrame

Para el modelo de datos de la tabla se tiene una clase ProductoTableModel que usa la clase Producto

Dentro del proyecto Netbeans crearemos primero las clases que daraacuten soporte al modelo de datos de la tabla

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

4

Crear Tablas de la base de datos de Ventas

Presione clic derecho en carnet luego clic en CREATE Script borre el coacutedigo que estaacute y agreacuteguele el coacutedigo que estaacute en el

anexo 1 luego presione clic en execute PgScript

Verificar que las tablas estaacuten creadas

Si no aparecen presione clic derecho clic en refresh sobre la base de datos carnet

Antildeadir registros desde un archivo

Descargue el archivo de datos desde el aula virtual

httpaulafiauesedusvmodresourceviewphpid=49943

Presione clic derecho sobre la tabla producto luego clic en import

5

Luego configure la ventana de importacioacuten como se muestra

Presione clic en import y espere a que termine la barra de progreso luego presione Done

6

Caso de uso Mantenimiento de productos

Nombre Mantenimiento de productos

Autor PRN315

Descripcioacuten Permite guardar modificar y eliminar productos de la base de datos

Actores Administrador

Precondiciones

Flujo normal de los eventos

1 El Administrador inicia el programa

2 El sistema muestra la interfaz de mantenimiento de productos con todos los productos encontrados en la base

de datos a traveacutes de una consulta inicial

3 El Administrador desea realizar una buacutesqueda de archivos se realiza la seccioacuten Buscar

4 El Administrador desea modificar uno de los producto se realiza la seccioacuten Actualizar

5 El Administrador desea ingresar un producto nuevo se realiza la seccioacuten Ingresar nuevo

6 El Administrador desea eliminar un producto se realiza la seccioacuten Eliminar

Flujos alternativos

Postcondiciones

7

Seccioacuten Buscar

1 El Administrador ingresa ellos criterios de buacutesqueda (coacutedigo y nombre) y presiona el botoacuten Buscar

2 El sistema realiza una consulta a la base de datos a partir de los criterios especificados y actualiza la tabla de

datos con los resultados encontrados

Seccioacuten Actualizar

1 El Administrador elige uno de los productos mostrados en la tabla haciendo doble clic el producto que desea

modificar

2 El sistema actualiza los controles de mantenimiento con los datos del producto seleccionado

3 El Administrador modifica los datos del producto y presiona el botoacuten actualizar

4 El registro fue actualizado satisfactoriamente El sistema actualiza el registro en la tabla

Cursos alternativos

4 Ocurrioacute un error al modificar el registro El sistema muestra un mensaje de error

Seccioacuten Ingresar nuevo

1 Los controles del formulario se encuentra vaciacuteos El Administrador llena los campos del formulario Coacutedigo

Nombre Cantidad en existencia y Precio unitario y presiona el botoacuten Guardar

2 El sistema almacena el registro en la base de datos y agrega el producto al final de la tabla

Cursos alternativos

1 Los controles tienen informacioacuten de un producto previamente seleccionado El Administrador presiona el botoacuten

Nuevo

12 El sistema limpia los controles

2 Ocurrioacute un error al guardar el registro El mensaje muestra un mensaje de error

8

Programacioacuten de Mantenimiento de productos

Haga un proyecto netbeans con el nombre CarnetLab06ejem01

Agregue un formulario jframe llamado MantenimientoProductos

9

Configuacuterelo como principal de ejecucioacuten

Disentildee la interfaz de usuario que corresponde al caso de uso descrito esta deberaacute tener la siguiente forma

Para los campos Cantidad en existencia y Precio unitario puede utilizar controles de tipo JFormattedTextField

Nota los dos recuadros negros son jPanel

10

Utilice los siguientes nombres de los controles

NOMBRE TIPO DE

COMPONENTE

DESCRIPCION

btnBuscar JButton El botoacuten que dispararaacute el evento clic que generaraacute la buacutesqueda de los

productos en la base de datos que correspondan a los criterios ingresados

btnElimina JButton El botoacuten que dispararaacute el evento clic que generaraacute la eliminacioacuten de los

productos seleccionados en la tabla

btnGuardar JButton El botoacuten que dispararaacute el evento clic que guardaraacute los datos ingresados en

los campos de la seccioacuten Mantenimiento

btnNuevo JButton El botoacuten que limpiaraacute el control del coacutedigo del producto cuando ya se haya

seleccionado un producto de la tabla

lBusqCod JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el coacutedigo del

producto

lBusqNombre JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el nombre del

producto

lCodigo JLabel Label (etiqueta) que corresponde al campo Coacutedigo del producto

lNombre JLabel Label (etiqueta) que corresponde al campo Nombre del producto

lCantidadExist JLabel Label (etiqueta) que corresponde al campo Cantidad en existencia del

producto

lPrecioUnit JLabel Label (etiqueta) que corresponde al Precio unitario del producto

tablaProductos JTable Tabla de producto

txtBusqCodigo JTextField Cuadro de texto para el criterio de buacutesqueda Coacutedigo del producto

txtBusqNombre JTextField Cuadro de texto para el criterio de buacutesqueda Nombre del producto

txtCodigo JTextField Cuadro de texto para la captura del Coacutedigo del producto

txtNombre JTextField Cuadro de texto para la captura del Nombre del producto

txtCantidadExistencia

JFormattedTextField Cuadro de texto con formato para la captura de la Cantidad en existencia

del producto

txtPrecioUnitario JFormattedTextField Cuadro de texto con formato para la captura del Precio unitario del

producto

Es opcional que le defina nombre

Para cada objeto presione clic derecho clic en Cambiar nombre de variable

11

Luego digite el nombre nuevo y presione aceptar

Modelo para registrar el producto en jFrame

Para el modelo de datos de la tabla se tiene una clase ProductoTableModel que usa la clase Producto

Dentro del proyecto Netbeans crearemos primero las clases que daraacuten soporte al modelo de datos de la tabla

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

5

Luego configure la ventana de importacioacuten como se muestra

Presione clic en import y espere a que termine la barra de progreso luego presione Done

6

Caso de uso Mantenimiento de productos

Nombre Mantenimiento de productos

Autor PRN315

Descripcioacuten Permite guardar modificar y eliminar productos de la base de datos

Actores Administrador

Precondiciones

Flujo normal de los eventos

1 El Administrador inicia el programa

2 El sistema muestra la interfaz de mantenimiento de productos con todos los productos encontrados en la base

de datos a traveacutes de una consulta inicial

3 El Administrador desea realizar una buacutesqueda de archivos se realiza la seccioacuten Buscar

4 El Administrador desea modificar uno de los producto se realiza la seccioacuten Actualizar

5 El Administrador desea ingresar un producto nuevo se realiza la seccioacuten Ingresar nuevo

6 El Administrador desea eliminar un producto se realiza la seccioacuten Eliminar

Flujos alternativos

Postcondiciones

7

Seccioacuten Buscar

1 El Administrador ingresa ellos criterios de buacutesqueda (coacutedigo y nombre) y presiona el botoacuten Buscar

2 El sistema realiza una consulta a la base de datos a partir de los criterios especificados y actualiza la tabla de

datos con los resultados encontrados

Seccioacuten Actualizar

1 El Administrador elige uno de los productos mostrados en la tabla haciendo doble clic el producto que desea

modificar

2 El sistema actualiza los controles de mantenimiento con los datos del producto seleccionado

3 El Administrador modifica los datos del producto y presiona el botoacuten actualizar

4 El registro fue actualizado satisfactoriamente El sistema actualiza el registro en la tabla

Cursos alternativos

4 Ocurrioacute un error al modificar el registro El sistema muestra un mensaje de error

Seccioacuten Ingresar nuevo

1 Los controles del formulario se encuentra vaciacuteos El Administrador llena los campos del formulario Coacutedigo

Nombre Cantidad en existencia y Precio unitario y presiona el botoacuten Guardar

2 El sistema almacena el registro en la base de datos y agrega el producto al final de la tabla

Cursos alternativos

1 Los controles tienen informacioacuten de un producto previamente seleccionado El Administrador presiona el botoacuten

Nuevo

12 El sistema limpia los controles

2 Ocurrioacute un error al guardar el registro El mensaje muestra un mensaje de error

8

Programacioacuten de Mantenimiento de productos

Haga un proyecto netbeans con el nombre CarnetLab06ejem01

Agregue un formulario jframe llamado MantenimientoProductos

9

Configuacuterelo como principal de ejecucioacuten

Disentildee la interfaz de usuario que corresponde al caso de uso descrito esta deberaacute tener la siguiente forma

Para los campos Cantidad en existencia y Precio unitario puede utilizar controles de tipo JFormattedTextField

Nota los dos recuadros negros son jPanel

10

Utilice los siguientes nombres de los controles

NOMBRE TIPO DE

COMPONENTE

DESCRIPCION

btnBuscar JButton El botoacuten que dispararaacute el evento clic que generaraacute la buacutesqueda de los

productos en la base de datos que correspondan a los criterios ingresados

btnElimina JButton El botoacuten que dispararaacute el evento clic que generaraacute la eliminacioacuten de los

productos seleccionados en la tabla

btnGuardar JButton El botoacuten que dispararaacute el evento clic que guardaraacute los datos ingresados en

los campos de la seccioacuten Mantenimiento

btnNuevo JButton El botoacuten que limpiaraacute el control del coacutedigo del producto cuando ya se haya

seleccionado un producto de la tabla

lBusqCod JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el coacutedigo del

producto

lBusqNombre JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el nombre del

producto

lCodigo JLabel Label (etiqueta) que corresponde al campo Coacutedigo del producto

lNombre JLabel Label (etiqueta) que corresponde al campo Nombre del producto

lCantidadExist JLabel Label (etiqueta) que corresponde al campo Cantidad en existencia del

producto

lPrecioUnit JLabel Label (etiqueta) que corresponde al Precio unitario del producto

tablaProductos JTable Tabla de producto

txtBusqCodigo JTextField Cuadro de texto para el criterio de buacutesqueda Coacutedigo del producto

txtBusqNombre JTextField Cuadro de texto para el criterio de buacutesqueda Nombre del producto

txtCodigo JTextField Cuadro de texto para la captura del Coacutedigo del producto

txtNombre JTextField Cuadro de texto para la captura del Nombre del producto

txtCantidadExistencia

JFormattedTextField Cuadro de texto con formato para la captura de la Cantidad en existencia

del producto

txtPrecioUnitario JFormattedTextField Cuadro de texto con formato para la captura del Precio unitario del

producto

Es opcional que le defina nombre

Para cada objeto presione clic derecho clic en Cambiar nombre de variable

11

Luego digite el nombre nuevo y presione aceptar

Modelo para registrar el producto en jFrame

Para el modelo de datos de la tabla se tiene una clase ProductoTableModel que usa la clase Producto

Dentro del proyecto Netbeans crearemos primero las clases que daraacuten soporte al modelo de datos de la tabla

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

6

Caso de uso Mantenimiento de productos

Nombre Mantenimiento de productos

Autor PRN315

Descripcioacuten Permite guardar modificar y eliminar productos de la base de datos

Actores Administrador

Precondiciones

Flujo normal de los eventos

1 El Administrador inicia el programa

2 El sistema muestra la interfaz de mantenimiento de productos con todos los productos encontrados en la base

de datos a traveacutes de una consulta inicial

3 El Administrador desea realizar una buacutesqueda de archivos se realiza la seccioacuten Buscar

4 El Administrador desea modificar uno de los producto se realiza la seccioacuten Actualizar

5 El Administrador desea ingresar un producto nuevo se realiza la seccioacuten Ingresar nuevo

6 El Administrador desea eliminar un producto se realiza la seccioacuten Eliminar

Flujos alternativos

Postcondiciones

7

Seccioacuten Buscar

1 El Administrador ingresa ellos criterios de buacutesqueda (coacutedigo y nombre) y presiona el botoacuten Buscar

2 El sistema realiza una consulta a la base de datos a partir de los criterios especificados y actualiza la tabla de

datos con los resultados encontrados

Seccioacuten Actualizar

1 El Administrador elige uno de los productos mostrados en la tabla haciendo doble clic el producto que desea

modificar

2 El sistema actualiza los controles de mantenimiento con los datos del producto seleccionado

3 El Administrador modifica los datos del producto y presiona el botoacuten actualizar

4 El registro fue actualizado satisfactoriamente El sistema actualiza el registro en la tabla

Cursos alternativos

4 Ocurrioacute un error al modificar el registro El sistema muestra un mensaje de error

Seccioacuten Ingresar nuevo

1 Los controles del formulario se encuentra vaciacuteos El Administrador llena los campos del formulario Coacutedigo

Nombre Cantidad en existencia y Precio unitario y presiona el botoacuten Guardar

2 El sistema almacena el registro en la base de datos y agrega el producto al final de la tabla

Cursos alternativos

1 Los controles tienen informacioacuten de un producto previamente seleccionado El Administrador presiona el botoacuten

Nuevo

12 El sistema limpia los controles

2 Ocurrioacute un error al guardar el registro El mensaje muestra un mensaje de error

8

Programacioacuten de Mantenimiento de productos

Haga un proyecto netbeans con el nombre CarnetLab06ejem01

Agregue un formulario jframe llamado MantenimientoProductos

9

Configuacuterelo como principal de ejecucioacuten

Disentildee la interfaz de usuario que corresponde al caso de uso descrito esta deberaacute tener la siguiente forma

Para los campos Cantidad en existencia y Precio unitario puede utilizar controles de tipo JFormattedTextField

Nota los dos recuadros negros son jPanel

10

Utilice los siguientes nombres de los controles

NOMBRE TIPO DE

COMPONENTE

DESCRIPCION

btnBuscar JButton El botoacuten que dispararaacute el evento clic que generaraacute la buacutesqueda de los

productos en la base de datos que correspondan a los criterios ingresados

btnElimina JButton El botoacuten que dispararaacute el evento clic que generaraacute la eliminacioacuten de los

productos seleccionados en la tabla

btnGuardar JButton El botoacuten que dispararaacute el evento clic que guardaraacute los datos ingresados en

los campos de la seccioacuten Mantenimiento

btnNuevo JButton El botoacuten que limpiaraacute el control del coacutedigo del producto cuando ya se haya

seleccionado un producto de la tabla

lBusqCod JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el coacutedigo del

producto

lBusqNombre JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el nombre del

producto

lCodigo JLabel Label (etiqueta) que corresponde al campo Coacutedigo del producto

lNombre JLabel Label (etiqueta) que corresponde al campo Nombre del producto

lCantidadExist JLabel Label (etiqueta) que corresponde al campo Cantidad en existencia del

producto

lPrecioUnit JLabel Label (etiqueta) que corresponde al Precio unitario del producto

tablaProductos JTable Tabla de producto

txtBusqCodigo JTextField Cuadro de texto para el criterio de buacutesqueda Coacutedigo del producto

txtBusqNombre JTextField Cuadro de texto para el criterio de buacutesqueda Nombre del producto

txtCodigo JTextField Cuadro de texto para la captura del Coacutedigo del producto

txtNombre JTextField Cuadro de texto para la captura del Nombre del producto

txtCantidadExistencia

JFormattedTextField Cuadro de texto con formato para la captura de la Cantidad en existencia

del producto

txtPrecioUnitario JFormattedTextField Cuadro de texto con formato para la captura del Precio unitario del

producto

Es opcional que le defina nombre

Para cada objeto presione clic derecho clic en Cambiar nombre de variable

11

Luego digite el nombre nuevo y presione aceptar

Modelo para registrar el producto en jFrame

Para el modelo de datos de la tabla se tiene una clase ProductoTableModel que usa la clase Producto

Dentro del proyecto Netbeans crearemos primero las clases que daraacuten soporte al modelo de datos de la tabla

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

7

Seccioacuten Buscar

1 El Administrador ingresa ellos criterios de buacutesqueda (coacutedigo y nombre) y presiona el botoacuten Buscar

2 El sistema realiza una consulta a la base de datos a partir de los criterios especificados y actualiza la tabla de

datos con los resultados encontrados

Seccioacuten Actualizar

1 El Administrador elige uno de los productos mostrados en la tabla haciendo doble clic el producto que desea

modificar

2 El sistema actualiza los controles de mantenimiento con los datos del producto seleccionado

3 El Administrador modifica los datos del producto y presiona el botoacuten actualizar

4 El registro fue actualizado satisfactoriamente El sistema actualiza el registro en la tabla

Cursos alternativos

4 Ocurrioacute un error al modificar el registro El sistema muestra un mensaje de error

Seccioacuten Ingresar nuevo

1 Los controles del formulario se encuentra vaciacuteos El Administrador llena los campos del formulario Coacutedigo

Nombre Cantidad en existencia y Precio unitario y presiona el botoacuten Guardar

2 El sistema almacena el registro en la base de datos y agrega el producto al final de la tabla

Cursos alternativos

1 Los controles tienen informacioacuten de un producto previamente seleccionado El Administrador presiona el botoacuten

Nuevo

12 El sistema limpia los controles

2 Ocurrioacute un error al guardar el registro El mensaje muestra un mensaje de error

8

Programacioacuten de Mantenimiento de productos

Haga un proyecto netbeans con el nombre CarnetLab06ejem01

Agregue un formulario jframe llamado MantenimientoProductos

9

Configuacuterelo como principal de ejecucioacuten

Disentildee la interfaz de usuario que corresponde al caso de uso descrito esta deberaacute tener la siguiente forma

Para los campos Cantidad en existencia y Precio unitario puede utilizar controles de tipo JFormattedTextField

Nota los dos recuadros negros son jPanel

10

Utilice los siguientes nombres de los controles

NOMBRE TIPO DE

COMPONENTE

DESCRIPCION

btnBuscar JButton El botoacuten que dispararaacute el evento clic que generaraacute la buacutesqueda de los

productos en la base de datos que correspondan a los criterios ingresados

btnElimina JButton El botoacuten que dispararaacute el evento clic que generaraacute la eliminacioacuten de los

productos seleccionados en la tabla

btnGuardar JButton El botoacuten que dispararaacute el evento clic que guardaraacute los datos ingresados en

los campos de la seccioacuten Mantenimiento

btnNuevo JButton El botoacuten que limpiaraacute el control del coacutedigo del producto cuando ya se haya

seleccionado un producto de la tabla

lBusqCod JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el coacutedigo del

producto

lBusqNombre JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el nombre del

producto

lCodigo JLabel Label (etiqueta) que corresponde al campo Coacutedigo del producto

lNombre JLabel Label (etiqueta) que corresponde al campo Nombre del producto

lCantidadExist JLabel Label (etiqueta) que corresponde al campo Cantidad en existencia del

producto

lPrecioUnit JLabel Label (etiqueta) que corresponde al Precio unitario del producto

tablaProductos JTable Tabla de producto

txtBusqCodigo JTextField Cuadro de texto para el criterio de buacutesqueda Coacutedigo del producto

txtBusqNombre JTextField Cuadro de texto para el criterio de buacutesqueda Nombre del producto

txtCodigo JTextField Cuadro de texto para la captura del Coacutedigo del producto

txtNombre JTextField Cuadro de texto para la captura del Nombre del producto

txtCantidadExistencia

JFormattedTextField Cuadro de texto con formato para la captura de la Cantidad en existencia

del producto

txtPrecioUnitario JFormattedTextField Cuadro de texto con formato para la captura del Precio unitario del

producto

Es opcional que le defina nombre

Para cada objeto presione clic derecho clic en Cambiar nombre de variable

11

Luego digite el nombre nuevo y presione aceptar

Modelo para registrar el producto en jFrame

Para el modelo de datos de la tabla se tiene una clase ProductoTableModel que usa la clase Producto

Dentro del proyecto Netbeans crearemos primero las clases que daraacuten soporte al modelo de datos de la tabla

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

8

Programacioacuten de Mantenimiento de productos

Haga un proyecto netbeans con el nombre CarnetLab06ejem01

Agregue un formulario jframe llamado MantenimientoProductos

9

Configuacuterelo como principal de ejecucioacuten

Disentildee la interfaz de usuario que corresponde al caso de uso descrito esta deberaacute tener la siguiente forma

Para los campos Cantidad en existencia y Precio unitario puede utilizar controles de tipo JFormattedTextField

Nota los dos recuadros negros son jPanel

10

Utilice los siguientes nombres de los controles

NOMBRE TIPO DE

COMPONENTE

DESCRIPCION

btnBuscar JButton El botoacuten que dispararaacute el evento clic que generaraacute la buacutesqueda de los

productos en la base de datos que correspondan a los criterios ingresados

btnElimina JButton El botoacuten que dispararaacute el evento clic que generaraacute la eliminacioacuten de los

productos seleccionados en la tabla

btnGuardar JButton El botoacuten que dispararaacute el evento clic que guardaraacute los datos ingresados en

los campos de la seccioacuten Mantenimiento

btnNuevo JButton El botoacuten que limpiaraacute el control del coacutedigo del producto cuando ya se haya

seleccionado un producto de la tabla

lBusqCod JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el coacutedigo del

producto

lBusqNombre JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el nombre del

producto

lCodigo JLabel Label (etiqueta) que corresponde al campo Coacutedigo del producto

lNombre JLabel Label (etiqueta) que corresponde al campo Nombre del producto

lCantidadExist JLabel Label (etiqueta) que corresponde al campo Cantidad en existencia del

producto

lPrecioUnit JLabel Label (etiqueta) que corresponde al Precio unitario del producto

tablaProductos JTable Tabla de producto

txtBusqCodigo JTextField Cuadro de texto para el criterio de buacutesqueda Coacutedigo del producto

txtBusqNombre JTextField Cuadro de texto para el criterio de buacutesqueda Nombre del producto

txtCodigo JTextField Cuadro de texto para la captura del Coacutedigo del producto

txtNombre JTextField Cuadro de texto para la captura del Nombre del producto

txtCantidadExistencia

JFormattedTextField Cuadro de texto con formato para la captura de la Cantidad en existencia

del producto

txtPrecioUnitario JFormattedTextField Cuadro de texto con formato para la captura del Precio unitario del

producto

Es opcional que le defina nombre

Para cada objeto presione clic derecho clic en Cambiar nombre de variable

11

Luego digite el nombre nuevo y presione aceptar

Modelo para registrar el producto en jFrame

Para el modelo de datos de la tabla se tiene una clase ProductoTableModel que usa la clase Producto

Dentro del proyecto Netbeans crearemos primero las clases que daraacuten soporte al modelo de datos de la tabla

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

9

Configuacuterelo como principal de ejecucioacuten

Disentildee la interfaz de usuario que corresponde al caso de uso descrito esta deberaacute tener la siguiente forma

Para los campos Cantidad en existencia y Precio unitario puede utilizar controles de tipo JFormattedTextField

Nota los dos recuadros negros son jPanel

10

Utilice los siguientes nombres de los controles

NOMBRE TIPO DE

COMPONENTE

DESCRIPCION

btnBuscar JButton El botoacuten que dispararaacute el evento clic que generaraacute la buacutesqueda de los

productos en la base de datos que correspondan a los criterios ingresados

btnElimina JButton El botoacuten que dispararaacute el evento clic que generaraacute la eliminacioacuten de los

productos seleccionados en la tabla

btnGuardar JButton El botoacuten que dispararaacute el evento clic que guardaraacute los datos ingresados en

los campos de la seccioacuten Mantenimiento

btnNuevo JButton El botoacuten que limpiaraacute el control del coacutedigo del producto cuando ya se haya

seleccionado un producto de la tabla

lBusqCod JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el coacutedigo del

producto

lBusqNombre JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el nombre del

producto

lCodigo JLabel Label (etiqueta) que corresponde al campo Coacutedigo del producto

lNombre JLabel Label (etiqueta) que corresponde al campo Nombre del producto

lCantidadExist JLabel Label (etiqueta) que corresponde al campo Cantidad en existencia del

producto

lPrecioUnit JLabel Label (etiqueta) que corresponde al Precio unitario del producto

tablaProductos JTable Tabla de producto

txtBusqCodigo JTextField Cuadro de texto para el criterio de buacutesqueda Coacutedigo del producto

txtBusqNombre JTextField Cuadro de texto para el criterio de buacutesqueda Nombre del producto

txtCodigo JTextField Cuadro de texto para la captura del Coacutedigo del producto

txtNombre JTextField Cuadro de texto para la captura del Nombre del producto

txtCantidadExistencia

JFormattedTextField Cuadro de texto con formato para la captura de la Cantidad en existencia

del producto

txtPrecioUnitario JFormattedTextField Cuadro de texto con formato para la captura del Precio unitario del

producto

Es opcional que le defina nombre

Para cada objeto presione clic derecho clic en Cambiar nombre de variable

11

Luego digite el nombre nuevo y presione aceptar

Modelo para registrar el producto en jFrame

Para el modelo de datos de la tabla se tiene una clase ProductoTableModel que usa la clase Producto

Dentro del proyecto Netbeans crearemos primero las clases que daraacuten soporte al modelo de datos de la tabla

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

10

Utilice los siguientes nombres de los controles

NOMBRE TIPO DE

COMPONENTE

DESCRIPCION

btnBuscar JButton El botoacuten que dispararaacute el evento clic que generaraacute la buacutesqueda de los

productos en la base de datos que correspondan a los criterios ingresados

btnElimina JButton El botoacuten que dispararaacute el evento clic que generaraacute la eliminacioacuten de los

productos seleccionados en la tabla

btnGuardar JButton El botoacuten que dispararaacute el evento clic que guardaraacute los datos ingresados en

los campos de la seccioacuten Mantenimiento

btnNuevo JButton El botoacuten que limpiaraacute el control del coacutedigo del producto cuando ya se haya

seleccionado un producto de la tabla

lBusqCod JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el coacutedigo del

producto

lBusqNombre JLabel Label (etiqueta) que corresponde al campo de buacutesqueda por el nombre del

producto

lCodigo JLabel Label (etiqueta) que corresponde al campo Coacutedigo del producto

lNombre JLabel Label (etiqueta) que corresponde al campo Nombre del producto

lCantidadExist JLabel Label (etiqueta) que corresponde al campo Cantidad en existencia del

producto

lPrecioUnit JLabel Label (etiqueta) que corresponde al Precio unitario del producto

tablaProductos JTable Tabla de producto

txtBusqCodigo JTextField Cuadro de texto para el criterio de buacutesqueda Coacutedigo del producto

txtBusqNombre JTextField Cuadro de texto para el criterio de buacutesqueda Nombre del producto

txtCodigo JTextField Cuadro de texto para la captura del Coacutedigo del producto

txtNombre JTextField Cuadro de texto para la captura del Nombre del producto

txtCantidadExistencia

JFormattedTextField Cuadro de texto con formato para la captura de la Cantidad en existencia

del producto

txtPrecioUnitario JFormattedTextField Cuadro de texto con formato para la captura del Precio unitario del

producto

Es opcional que le defina nombre

Para cada objeto presione clic derecho clic en Cambiar nombre de variable

11

Luego digite el nombre nuevo y presione aceptar

Modelo para registrar el producto en jFrame

Para el modelo de datos de la tabla se tiene una clase ProductoTableModel que usa la clase Producto

Dentro del proyecto Netbeans crearemos primero las clases que daraacuten soporte al modelo de datos de la tabla

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

11

Luego digite el nombre nuevo y presione aceptar

Modelo para registrar el producto en jFrame

Para el modelo de datos de la tabla se tiene una clase ProductoTableModel que usa la clase Producto

Dentro del proyecto Netbeans crearemos primero las clases que daraacuten soporte al modelo de datos de la tabla

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

12

package carnetlab06ejem01

public class Producto

String codigo

String nombre

Double cantidadExistencia

Double precioUnitario

package carnetlab06ejem01

import javautilArrayList

import javautilList

import javaxswingtableAbstractTableModel

public class ProductoTableModel extends AbstractTableModel

ListltProductogt productos = new ArrayListltProductogt()

Override

public int getRowCount()

return productossize()

Override

public int getColumnCount()

return 4

Override

public Object getValueAt(int rowIndex int columnIndex)

Producto producto = productosget(rowIndex)

Object valor = null

switch(columnIndex)

case 0 valor = productocodigo

break

case 1 valor = productonombre

break

case 2 valor = productocantidadExistencia

break

case 3 valor = productoprecioUnitario

return valor

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

13

Modificar el jFrame(Definir la instancia de ProductoTableModel)

Ahora modificaremos el coacutedigo generado por NetBeans cuando creamos el formulario

Lo primero seraacute agregar el modelo de la tabla ProductoTableModel a la clase del formulario (MantenimientoProductos)

Luego en la ventana de disentildeo presione clic derecho en el jTable y clic en Contenido de la tabla

Buscamos la opcioacuten del modelo y lo definimos como se muestra

Luego presionamos clic en cerrar

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

14

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla Haremos esto en un

meacutetodo llamado iniciarlizarColumnas que invocaremos desde el constructor del formulario

hellip

public MantenimientoProductos()

initComponents()

inicializarColumnas()

private void inicializarColumnas()

TableColumnModel tColumnModel = new DefaultTableColumnModel()

for (int i = 0 i lt 4 i++)

TableColumn col = new TableColumn(i)

switch (i)

case 0

colsetHeaderValue(Coacutedigo)

break

case 1

colsetHeaderValue(Nombre)

break

case 2

colsetHeaderValue(Existencia)

break

case 3

colsetHeaderValue(Precio)

tColumnModeladdColumn(col)

tablaProductossetColumnModel(tColumnModel)

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

15

Hasta ahora al ejecutar el proyecto tendremos una ventana como la siguiente

Conexioacuten a Base de Datos

Agregar libreriacutea de Postgree

Sobre la carpeta biblioteca presionar clic derecho clic en Agregar biblioteca

Seleccionar el Driver que se muestra y presionar clic en Antildeadir biblioteca

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

16

Ahora agregaremos un atributo que llamaremos Conexion al formulario de tipo Connection provisto por el Driver de

conexioacuten que hemos agregado al proyecto

Ademaacutes programaremos los meacutetodos conectar y consultaInicial que nos permitiraacuten conectarnos a la base de datos y

realizar la consulta de todos los productos que existen en la base de datos

La clase Driver cuenta con un meacutetodo estaacutetico getConnection que es el que permite realizar la conexioacuten a la base de datos

Este es un meacutetodo sobrecargado que tiene la siguientes formas

Meacutetodos relevantes

static Connection getConnection(String url)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada

static Connection getConnection(String url Properties info)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con las

propiedades especificadas en el paraacutemetro info

static Connection getConnection(String url String user String password)

Permite establecer una conexioacuten a la base de datos que corresponde a la URL especificada con el

usuario y clave especificados

Usaremos la tercera forma para establecer la conexioacuten a la base de datos

Antes crearemos un atributo que serviraacute para hacer referencia al objeto conexioacuten que crearemos que nos permitiraacute que la

conexioacuten pueda ser accedida desde cualquier meacutetodo de la clase

Nota la clase de conexioacuten deberaacute poseer una contrasentildea que tenga letras nuacutemeros y mayuacutesculas y minuacutesculas

como rdquoprn315CARNETrdquo por lo que puede crear la el usuario de postgres como se muestra en el anexo 2 Pero si

utiliza la conexioacuten creada en la guiacutea 5 use las indicaciones del anexo 3

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

17

La consulta inicial seraacute realizada con la sentencia SQL SELECT FROM producto que indica a la base de datos que

devuelva todos los campos () de la tabla producto (FROM producto)

La clase Connection nos permite crear objetos a traveacutes de los cuales podemos ejecutar las sentencias SQL Entre los

meacutetodos maacutes relevantes de la clase Connection estaacuten

public class MantenimientoProductos extends javaxswingJFrame

public ProductoTableModel productoTModel = new ProductoTableModel()

private Connection conexion

Creates new form DatosPersonales

public MantenimientoProductos()

initComponents()

inicializarColumnas()

conectar()

consultaInicial()

private void conectar()

try

conexion = DriverManagergetConnection(jdbcpostgresqllocalhost5432carnet carnet prn315CARNET)

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

18

Meacutetodos relevantes

void close()

Libera el objeto de conexioacuten de la base de datos y los recursos JDBC

Statement createStatement()

Crea un objeto Statement para enviar sentencias SQL a la base de datos

Statement createStatement(int resultSetType int resultSetConcurrency)

Crea un objeto Statement que generaraacute objetos ResultSet con los tipos y la concurrencia

especificados

PreparedStatement prepareStatement(String sql)

Crea un objeto PreparedStatement para enviar consultar SQL parametrizadas a la base de datos

PreparedStatement prepareStatement(String sql String[] columnNames)

Crea un objeto PreparedStatement por defecto capaz de retornar valores autogenerados para las

llaves designados en el arreglo recibido como paraacutemetro

Como puede observarse la sentencia de la consulta inicial puede ser ejecutada por un objeto de tipo Statement dado que no

es necesario que reciba alguacuten valor como paraacutemetro

Ahora debemos saber como recuperar los datos que devolveraacute la sentencia SQL Para ello consultaremos los meacutetodos maacutes

relevantes de la clase Statement

Meacutetodos relevantes

boolean execute(String sql)

Ejecuta la sentencia SQL recibida que puede devolver muacuteltiples resultados

ResultSet executeQuery(String sql)

Ejecuta la consulta SQL recibida que puede devolver un uacutenico objeto ResultSet

int executeUpdate(String sql)

Ejecuta la consulta SQL recibida que puede ser una sentencia INSERT UPDATE o DELETE o una sentencia

SQL que no devuelva ninguacuten valor como una sentencia SQL DDL

ResultSet getResultSet()

Devuelve el resultado actual como un objeto de tipo ResultSet

Como puede observarse los resultados de una consulta SQL son devueltos en un objeto de tipo ResultSet Este tipo de

objetos sirven para recibir los datos de una consulta y poder manipularlos de una forma parecida a como manipulariacuteamos

una matriz de datos o una tabla

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

19

Al consultar el API de la clase ResultSet encontramos los siguientes meacutetodos como los maacutes importantes

Meacutetodos relevantes

Date getDate(int columnIndex)

Devuelve el valor de la columna indicada por el paraacutemetro en la fila actual del objeto como un tipo

javasqlDate

double getDouble(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo double

float getFloat(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo float

int getInt(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo int

long getLong(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo long

String getString(int columnIndex)

Devuelve el valor de la columna indicada como parraacutemetro en la fila actual del objeto como un

tipo String

boolean last()

Mueve el cursor (el cursor del ResultSet) a la uacuteltima fila del ResultSet Devuelve true si la fila en la

que se posiciona el cursor es vaacutelida false si no hay filas

boolean next()

Mueve el cursor una fila hacia adelante desde la posicioacuten actual en el ResultSet Devuelve true si la

fila en la que se posiciona el cursor es vaacutelida false si no hay maacutes filas

boolean previous()

Mueve el cursor una fila hacia atraacutes en el objeto ResultSet Devuelve true si la fila en la que se

posiciona el cursor es vaacutelida false si no hay maacutes filas

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

20

Al ejecutar el formulario veremos que la tabla ahora tendraacute los datos que se encuentran almacenados en la tabla producto de

la base de datos carnet

Noacutetese que para llenar la tabla ha sido necesario recorrer el cursor resultados construir un objeto Producto para cada fila

devuelta por la consulta y agregarla a la lista asociada al modelo de la tabla

private void consultaInicial()

try

String sentenciaSql = SELECT FROM producto

Statement statement = thisconexioncreateStatement()

ResultSet resultado = statementexecuteQuery(sentenciaSql)

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(codigo)

productonombre = resultadogetString(nombre)

productocantidadExistencia = resultadogetDouble(cantidad_existencia)

productoprecioUnitario = resultadogetDouble(precio_unitario)

thisproductoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

21

Programacioacuten de los botones de Accioacuten

Programaremos ahora la accioacuten para el evento clic del botoacuten Buscar

private void btnBuscarActionPerformed(javaawteventActionEvent evt)

productoTModelproductosclear()

try

PreparedStatement statement = null

String codigo = txtBusqCodigogetText()toString()

String nombre = txtBusqNombregetText()toString()

String sentenciaSql = SELECT FROM producto

if (codigoisEmpty())

if (nombreisEmpty())

sentenciaSql += WHERE idproducto ILIKE OR nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

statementsetString(2 + nombre + )

else

sentenciaSql += WHERE idproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 codigo + )

else

if (nombreisEmpty())

sentenciaSql += WHERE nomproducto ILIKE

statement = thisconexionprepareStatement(sentenciaSql)

statementsetString(1 + nombre + )

else

statement = thisconexionprepareStatement(sentenciaSql)

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

22

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto()

productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Podemos probar la buacutesqueda

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

23

Puede observarse que dependiendo de los valores de los campos de buacutesqueda se construye una sentencia SQL con los

filtros necesarios

Note que la lista de producto asociada al modelo de la tabla es limpiada (vaciada) antes de realizar la buacutesqueda

Si ambos campos tienen valor la consulta resultante seraacute SELECT FROM producto WHERE codigo ilike codigo OR

nombre ilike nombre que indica a la base de datos que devuelva todos los atributos () de los registros de la tabla

producto (FROM producto) que cumplan con la condicioacuten (WHERE) de que el valor del campo codigo del registro inicie

con el valor especificado en el control txtBusqCodigo (que ha sido guardado en la variable codigo) y todos aquellos cuyo

nombre contengan el valor especificado en el control txtBusqNombre (que ha sido guardado en la variable nombre)

Note que la barra de desplazamiento (scroll) de la tabla es reiniciada a partir del nuevo resultado de la tabla para que

despueacutes la tabla sea redibujada en el formulario

Programaremos ahora el botoacuten Eliminar seleccionados Por defecto la tabla tiene un comportamiento que permite la

muacuteltiple seleccioacuten de filas Necesitamos ahora un meacutetodo que nos devuelva esas filas seleccionadas

Meacutetodos relevantes

void clearSelection()

Deshace la seleccioacuten todos las filas y columnas que hayan sido seleccionadas

int getSelectedColumn()

Devuelve el iacutendice de la primera columna seleccionada -1 si ninguna columna ha sido

seleccionada

int getSelectedColumnCount()

Devuelve el nuacutemero de columnas seleccionadas

int[] getSelectedColumns()

Devuelve los indices de todas las columnas seleccionadas

int getSelectedRow()

Devuelve el iacutendice de la primera fila seleccionada -1 si ninguna fila ha sido seleccionada

int getSelectedRowCount()

Devuelve el nuacutemero de filas seleccionadas

int[] getSelectedRows()

Devuelve el indice de todas las filas seleccionadas

int rowAtPoint(Point point)

Devuelve el indice de la fila indicada por el punto recibido como paraacutemetro o -1 si el resultado

estaacute fuera del intervalo [0 getRowCount() -1]

private void btnEliminaActionPerformed(javaawteventActionEvent evt)

Indices de las filas seleccionadas

int[] indices = tablaProductosgetSelectedRows()

ListltProductogt aEliminar = new ArrayListltProductogt()

for (int i indices)

Producto producto = productoTModelproductosget(i)

String sentenciaSql = DELETE FROM producto WHERE idproducto =

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

24

aEliminaradd(producto)

try

PreparedStatement prepStat = conexionprepareStatement(sentenciaSql)

prepStatsetString(1 productocodigo)

prepStatexecuteUpdate()

JOptionPaneshowMessageDialog(this Elimino correctamente + productocodigo)

UpdateJTable()

catch (SQLException ex)

LoggergetLogger(MantenimientoProductosclassgetName())log(LevelSEVERE null ex)

tablaProductosrepaint()

Nota

Por problemas de actualizacioacuten del objeto jTable se ha tenido que hacer un meacutetodo UpdateJTable()

En el que se actualiza dicho objeto despueacutes de eliminar

private void UpdateJTable()

productoTModelproductosclear()

try

PreparedStatement statement = null

String sentenciaSql = SELECT FROM producto

statement = thisconexionprepareStatement(sentenciaSql)

ResultSet resultado = statementexecuteQuery()

while (resultadonext())

Producto producto = new Producto() productocodigo = resultadogetString(idproducto)

productonombre = resultadogetString(nomproducto)

productoprecioUnitario = resultadogetDouble(precproducto)

productocantidadExistencia = resultadogetDouble(exisproducto)

productoTModelproductosadd(producto)

tablaProductosrepaint()

catch (SQLException ex)

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

25

JOptionPaneshowMessageDialog(this Error al recuperar los productos de la base de datos)

exprintStackTrace()

Noacutetese que hemos usado en este caso un PreparedStatement en sustitucioacuten de un Statement Como

puede consultarse en la tabla de meacutetodos de la clase Connection un PreparedStatement es un Statement

que admite paraacutemetros para ser sustituidos en la consulta

Pruebe el botoacuten Eliminar

Primero presione clic en el registro a eliminar y luego el botoacuten de eliminar

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

26

Meacutetodos relevantes

boolean execute()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser cualquier tipo de sentencia SQL

ResultSet executeQuery()

Ejecuta la sentencia SQL en el PreparedStatement y devuelve el objeto ResultSet generado por la

consulta

int executeUpdate()

Ejecuta la sentencia SQL en el PreparedStatement que puede ser una sentencia de tipo DML como

INSERT UPDATE o DELETE o una sentencia de tipo DDL

void setDouble(int parameterIndex double x)

Asigna al paraacutemetro indicado por el parameterIndex el valor double especificado

void setFloat(int parameterIndex float x)

Asigna al paraacutemetro indicado por el parameterIndex el valor float especificado

void setInt(int parameterIndex int x)

Asigna al paraacutemetro indicado por el parameterIndex el valor int especificado

void setLong(int parameterIndex long x)

Asigna al paraacutemetro indicado por el parameterIndex el valor long especificado

Programaremos ahora el evento que nos permita guardar un nuevo producto en la base de datos El caso de uso especifica

que cuando el Administrador desee ingresar un producto nuevo debe llenar los controles que se encuentran en la seccioacuten

Mantenimiento y luego presionar el botoacuten Guardar

El proceso consiste en crear un nuevo objeto de tipo Producto asignarle los valores establecidos por el usuario en el

formulario y ejecutar la consulta de insercioacuten

La sentencia SQL de insercioacuten utilizada tendraacute la siguiente forma INSERT INTO producto(codigo nombre

cantidad_existencia precio_unitario) VALUES(productocodigo productonombre productocantidadExistencia

productoprecioUnitario) que le indica a la base de datos que debe insertar en la tabla producto (INSERT INTO producto)

los valores que se detallan posteriormente en el orden en el que aparecen los campos entre pareacutentesis Los valores

especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla

private void btnGuardarActionPerformed(javaawteventActionEvent evt) try Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

String sentenciaSql = INSERT INTO producto(idproducto nomproducto precproductoexisproducto)

VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo) preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productoprecioUnitario)

preparedStatementsetDouble(4 productocantidadExistencia)

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

27

preparedStatementexecute()

productoTModelproductosadd(producto)

tablaProductosrepaint() catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el evento en la tabla que nos permita saber el producto que el usuario desea modificar La

descripcioacuten del caso de uso establece que cuando el usuario desee modificar un producto deberaacute hacer doble clic en la fila

del producto de su intereacutes

Ahora deberemos encontrar una forma de saber cuaacutendo se trata de un registro nuevo (insercioacuten) y cuando se trata de un

registro ya existente (actualizar) Es loacutegico que cuando no se haya seleccionado ninguacuten producto de la tabla el formulario se

encontraraacute en modo insercioacuten y que si se ha seleccionado un producto se encontraraacute en modo actualizacioacuten

Para ello usaremos 2 atributos de control El primero guardar de tipo boolean nos permitiraacute saber cuaacutendo el aacuterea de

Mantenimiento del formulario se encuentra en modo de insercioacuten y cuando en modo de actualizacioacuten

Para saber cuaacutel producto ha seleccionado el usuario programaremos el evento mouseClicked de la tabla que nos permitiraacute

saber cuaacutel es la fila seleccionada y por lo tanto el producto seleccionado

Una vez seleccionado el producto los controles del aacuterea Mantenimiento deberaacuten ser llenados con los valores del producto

seleccionado Y una vez llenados el usuario podraacute modificarlos para su posterior actualizacioacuten en la base de datos

Usaremos el mismo botoacuten para este efecto El segundo atributo de control seraacute entonces un objeto de tipo Producto que

permita guardar el uacuteltimo producto seleccionado

private void tablaProductosMouseClicked(javaawteventMouseEvent evt)

TODO add your handling code here

int clics = evtgetClickCount()

int row = tablaProductosrowAtPoint(evtgetPoint())

if (clics == 2)

Producto p = productoTModelproductosget(row)

productoActual = p

txtCodigosetText(pcodigo)

txtNombresetText(pnombre)

txtCantidadExistenciasetText(StringvalueOf(pcantidadExistenciadoubleValue()))

txtPrecioUnitariosetText(StringvalueOf(pprecioUnitariodoubleValue()))

guardar = false

Noacutetese al hacer guarde= false estamos indicando que el formulario ya no se encuentra en modo de edicioacuten

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

28

private void btnGuardarActionPerformed(javaawteventActionEvent evt)

try

if (guardar)

Producto producto = new Producto()

productocodigo = txtCodigogetText()

productonombre = txtNombregetText()

productocantidadExistencia = DoubleparseDouble(txtCantgetText())

productoprecioUnitario = DoubleparseDouble(txtPreciogetText())

String sentenciaSql = INSERT INTO producto(codigo nombre cantidad_existencia precio_unitario) VALUES

+ ()

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 productocodigo)

preparedStatementsetString(2 productonombre)

preparedStatementsetDouble(3 productocantidadExistencia)

preparedStatementsetDouble(4 productoprecioUnitario)

preparedStatementexecute()

productoTModelproductosadd(producto)

else

String sentenciaSql = UPDATE producto SET nomproducto = exisproducto = precproducto= WHERE idproducto =

PreparedStatement preparedStatement = conexionprepareStatement(sentenciaSql)

preparedStatementsetString(1 txtNombregetText())

preparedStatementsetDouble(2 DoublevalueOf(txtCantidadExistenciagetText()))

preparedStatementsetDouble(3 DoubleparseDouble(txtPrecioUnitariogetText()))

preparedStatementsetString(4 txtCodigogetText())

preparedStatementexecuteUpdate()

productoActualcantidadExistencia = DoubleparseDouble(txtCantidadExistenciagetText())

productoActualcodigo = txtCodigogetText()

productoActualnombre = txtNombregetText()

productoActualprecioUnitario = DoubleparseDouble(txtPrecioUnitariogetText())

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

29

tablaProductosrepaint()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Error al guardar el producto)

exprintStackTrace()

Programaremos ahora el botoacuten Nuevo que permite quitar la referencia a cualquier producto que se haya seleccionado

previamente e indicar el formulario que entraraacute en un modo de insercioacuten

private void btnNuevoActionPerformed(javaawteventActionEvent evt)

TODO add your handling code here

txtCodigosetText()

guardar = true

productoActual = null

Cuando se hace una conexioacuten a una base de datos se crea una conexioacuten directa entre el equipo desde el que se estaacute

realizando la conexioacuten y el servidor de la base de datos

Para evitar que la base de datos mantenga la conexioacuten abierta en espera de nuevas solicitudes nuestro programa debe

asegurarse de cerrar la conexioacuten cuando termine su ejecucioacuten Para ello programaremos el evento formWindowClossing

que como su nombre lo indica seraacute lanzado cuando el formulario se esteacute cerrando

Para crear el evento haga clic derecho sobre el formulario que hemos creado (en un aacuterea donde no haya otro control) elija

la opcioacuten Events del menuacute contextual elija la opcioacuten Window y luego windoCclosing NetBeans generaraacute el meacutetodo

escuchador del evento y en eacutel agregaremos el coacutedigo necesario para cerrar la conexioacuten a la base de datos

private void formWindowClosing(javaawteventWindowEvent evt)

TODO add your handling code here

try

conexionclose()

catch (SQLException ex)

JOptionPaneshowMessageDialog(this Ocurrioacute un error al cerrar la conexioacuten a la base de datos)

JOptionPaneshowMessageDialog(this La conexioacuten a la base de datos ha sido cerrada)

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

30

Ejercicio Adicional

1 Agregue a la aplicacioacuten tomando de referencia el coacutedigo anterior para resolver el caso de uso

Mantenimiento de Clientes

Anexo 1

Coacutedigo SQL para crear el modelo a utilizar en la guiacutea

==============================================================

DBMS name PostgreSQL 8

Created on 10102014 094909 pm

==============================================================

drop index CLIENTE_PK

drop table CLIENTE

drop index RELATIONSHIP_3_FK

drop index RELATIONSHIP_2_FK

drop index DETALLEVENTA_PK

drop table DETALLEVENTA

drop index PRODUCTO_PK

drop table PRODUCTO

drop index RELATIONSHIP_1_FK

drop index VENTA_PK

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

31

drop table VENTA

==============================================================

Table CLIENTE

==============================================================

create table CLIENTE (

IDCLIENTE CHAR(4) not null

NOMCLIENTE VARCHAR(30) not null

APELCLIENTE VARCHAR(30) not null

constraint PK_CLIENTE primary key (IDCLIENTE)

)

==============================================================

Index CLIENTE_PK

==============================================================

create unique index CLIENTE_PK on CLIENTE (

IDCLIENTE

)

==============================================================

Table DETALLEVENTA

==============================================================

create table DETALLEVENTA (

NUMVENTA CHAR(6) not null

IDPRODUCTO CHAR(4) not null

CANTIDADPRODUCTOVENDIDO NUMERIC(82) not null

PRECIOPRODUCTOVENDIDO NUMERIC(162) not null

constraint PK_DETALLEVENTA primary key (NUMVENTA IDPRODUCTO)

)

==============================================================

Index DETALLEVENTA_PK

==============================================================

create unique index DETALLEVENTA_PK on DETALLEVENTA (

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

32

NUMVENTA

IDPRODUCTO

)

==============================================================

Index RELATIONSHIP_2_FK

==============================================================

create index RELATIONSHIP_2_FK on DETALLEVENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_3_FK

==============================================================

create index RELATIONSHIP_3_FK on DETALLEVENTA (

IDPRODUCTO

)

==============================================================

Table PRODUCTO

==============================================================

create table PRODUCTO (

IDPRODUCTO CHAR(4) not null

NOMPRODUCTO VARCHAR(100) not null

PRECPRODUCTO NUMERIC(162) not null

EXISPRODUCTO NUMERIC(82) not null

constraint PK_PRODUCTO primary key (IDPRODUCTO)

)

==============================================================

Index PRODUCTO_PK

==============================================================

create unique index PRODUCTO_PK on PRODUCTO (

IDPRODUCTO

)

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

33

==============================================================

Table VENTA

==============================================================

create table VENTA (

NUMVENTA CHAR(6) not null

IDCLIENTE CHAR(4) not null

FECVENTA DATE not null

TOTVENTA NUMERIC(162) not null

IMPVENTA NUMERIC(162) not null

TOTCONIMPVENTA NUMERIC(162) not null

constraint PK_VENTA primary key (NUMVENTA)

)

==============================================================

Index VENTA_PK

==============================================================

create unique index VENTA_PK on VENTA (

NUMVENTA

)

==============================================================

Index RELATIONSHIP_1_FK

==============================================================

create index RELATIONSHIP_1_FK on VENTA (

IDCLIENTE

)

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_VENTA foreign key (NUMVENTA)

references VENTA (NUMVENTA)

on delete restrict on update restrict

alter table DETALLEVENTA

add constraint FK_DETALLEV_RELATIONS_PRODUCTO foreign key (IDPRODUCTO)

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict

34

references PRODUCTO (IDPRODUCTO)

on delete restrict on update restrict

alter table VENTA

add constraint FK_VENTA_RELATIONS_CLIENTE foreign key (IDCLIENTE)

references CLIENTE (IDCLIENTE)

on delete restrict on update restrict