crud de tabla producto con swing -...
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