Anda di halaman 1dari 37

UNIVERSIDAD DE EL SALVADOR

ESCUELA DE INGENIERIA DE SISTEMAS INFORMATICOS


PROGRAMACION III

ARCHIVOS Y BASES DE DATOS

Manejo de archivos
Ejemplo
Realizaremos un ejemplo sobre como crear un archivo de texto, escribir en l y luego leer su contenido.

Nombre:

Crear archivo de texto

Autor:

PRN315

Descripcin:

Crear un archivo de texto e ingresar 3 lneas como contenido

Actores:

Usuario

Precondiciones:
Flujo normal de los eventos:
1. El Usuario inicia el programa.
2. El sistema despliega una pantalla en la que el indicar la ruta y nombre del archivo que desea crear.
3. El selecciona la ruta y escribe el nombre del archivo.
4. El sistema muestra una secuencia de tres mensajes de captura de datos en la que el Usuario escribir el
contenido que desea guardar en el archivo.
Flujos alternativos:
4. No fue posible crear el archivo. El sistema muestra el mensaje: Error al intentar abrir el archivo.
Postcondiciones:

Para resolver este problema primero debemos saber lo que debemos hacer para mostrar una ventana para Abrir un archivo.
La clase JFileChooser nos permite desplegar este tipo de ventanas.
1

Los constructores y los mtodos de dicha clase las encontramos al consultar el API de Java.

Constructores
JFileChooser()
Construye un JFileChooser (selector de archivos) que se posicionar en el directorio por defecto del usuario.
JFileChooser(File currentDirectory)
Construye un JFileChooser que se posicionar en la ruta del archivo recibido como parmetro.

Mtodos relevantes
void cancelSelection()

Invocado por la Interfaz de usuario (UI) cuando el usuario hace clic en el botn Cancelar.
protected

JDialog createDialog(Component parent)

Crea y retorna un nuevo objeto JDialog que ser desplegado en el centro del componente recibido
como parmetro.
File getSelectedFile()

Devuelve el archivo seleccionado.


File[] getSelectedFiles()

Devuelve un arreglo de archivo seleccionados, si el selector de archivo ha sido configurado para


permitir selecciones mltiples.
void setDialogTitle(String dialogTitle)

Asigna la cadena recibida comoparmetro como ttulo de la ventana mostrada por el selector de
archivos.
void setFileFilter(FileFilter filter)

Asigna el filtro de archivos recibido.


int showOpenDialog(Component parent)

Provee de una ventana de seleccin de archivo del tipo Abrir archivo


int showSaveDialog(Component parent)

Provee una ventana de almacenamiento de archivos del tipo Guardar archivo.

Podemos usar algunos de estos mtodos para mostrar una ventana de seleccin de archivo, que nos permitir crear el
archivo en el disco duro, y devolvernos la referencia al mismo para su manipulacin.
Ntese que es posible asignar un filtro de archivo a la ventana. Esto servir para asegurarnos que los archivos
seleccionados/creados, sean de este formato.
El filtro de archivos puede ser creado con la clase FileNameExtensionFilter, que permite definir un filtro para las
extensiones de los nombres de archivo. Al consultar el API de Java, encontramos que esta clase tiene las siguientes
caractersticas:

Lista de constructores
FileNameExtensionFilter(String description, String extensions)
Crea un Filtro de extensiones de nombres de archivos con la descripcin especificada y la extensin del nombre del archivo..

public class EjemploArchivo {

public static void main(String[] args) {

JOptionPane.showMessageDialog(null, "Iniciaremos escribiendo un archivo.\nNombre el


archivo con su nmero de carnet");
escribirArchivo();
}

public static void escribirArchivo() {


JOptionPane.showMessageDialog(null, "Ejemplo crear archivo");

//Se crea el filtro de archivos


FileNameExtensionFilter filtro = new FileNameExtensionFilter("Archivos de texto",
"txt");

//El objeto Swing que mostrar la ventana para seleccionar el archivo


JFileChooser seleccionador = new JFileChooser();
seleccionador.setFileFilter(filtro);
seleccionador.setDialogTitle("Abrir");

//Muestra la ventana de dilogo


seleccionador.showOpenDialog(null);

if (seleccionador.getSelectedFile() != null) {
File archivo = seleccionador.getSelectedFile();
}
}

El objeto archivo de tipo File, es la referencia que tenemos al archivo creado en el disco. Nos interesa ahora encontrar una
forma de escribir los datos en el archivo.
Al consultar el API de Java, encontraremos la clase PrintWriter, que entre otras operaciones, permite escribir los datos en un
archivo.

Constructores

PrintWriter(File file)
Crea un nuevo objeto de escritura/impresin, sin un control de flujo de lnea automtico, para el archivo recibido como
parmetro.
PrintWriter(String fileName)
Crea un nuevo objeto de escritura/impresin sin control de flujo de lnea automtico ,para el archivo recibido como parmetro.

Mtodos relevantes
void close()
Cierra el stream y libera cualquier recurso del sistema asociado a l.
void println(long x)
Imprime (en el archivo) el dato de tipo long recibido como parmetro y termina la lnea.
void println(Object x)
Imprime (en el archivo) el dato recibido como parmetro y termina la lnea.
void println(String x)
Imprime (en el archivo) el dato recibido como parmetro y termina la lnea.

public static void escribirArchivo() {


JOptionPane.showMessageDialog(null, "Ejemplo crear archivo");

//Se crea el filtro de archivos


FileNameExtensionFilter filtro = new FileNameExtensionFilter("Archivos de texto",
"txt");

//El objeto Swing que mostrar la ventana para seleccionar el archivo


JFileChooser seleccionador = new JFileChooser();
seleccionador.setFileFilter(filtro);
seleccionador.setDialogTitle("Abrir");

//Muestra la ventana de dilogo


seleccionador.showOpenDialog(null);

if (seleccionador.getSelectedFile() != null) {
File archivo = seleccionador.getSelectedFile();

PrintWriter flujoSalida = null;

try {
flujoSalida = new PrintWriter(archivo);
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "Error al intentar abrir el archivo" +
archivo);
System.exit(0);
}

JOptionPane.showMessageDialog(null, "Deber ingresa tres lneas de texto");

for (int i = 1; i <= 3; i++) {


String linea = JOptionPane.showInputDialog("Ingrese la lnea " + i);
flujoSalida.println(i + " " + linea);
}

flujoSalida.close();

JOptionPane.showMessageDialog(null, "El texto fue guardado en el archivo: " +


archivo);
}
}

De igual forma, ahora podemos resolver el caso de uso para leer cualquier archivo de texto.

Nombre:

Consultar contenido de archivo

Autor:

PRN315

Descripcin:

Consultar el contenido de un archivo de texto

Actores:

Usuario

Precondiciones:
Flujo normal de los eventos:
1. El Usuario inicia el programa.
2. El sistema despliega una pantalla en la que el indicar la ruta y nombre del archivo que desea consultar.
3. El selecciona el archivo.
4. El sistema lee el archivo y muestra el contenido.
Flujos alternativos:
4. No fue posible crear el archivo. El sistema muestra el mensaje: Error al intentar abrir el archivo.
Postcondiciones:

El problema que nos plantea este caso de uso es encontrar la forma de leer el contenido del archivo para poder desplegarlo
en la pantalla. Para ello, podemos usar la clase Scanner, que ya hemos usado para leer texto ingresado desde el teclado.

Constructores
Scanner(File source)
Construye un objeto Scanner que provee los valores ledos desde el archivo especificado como parmetro.
Scanner(File source, String charsetName)
Construye un objeto Scanner que provee los valores ledos desde el archivo especificado como parmetro.
Scanner(InputStream source)
Construye un objeto Scanner que provee los valores ledos desde el flujo de entrada especificado como parmetro.

Mtodos relevantes
void close()
Cierra el Scanner
String next()
Encuentra y devuelve el siguiente token completo desde el objeto que lo invoca.
String next(Pattern pattern)
Devuelve el siguiente token si este coincide con el patrn especificado.
String nextLine()
Hace que el objeto Scanner que invoca al mtodo avance a la siguiente lnea y devuelva la entrada
encontrada en la lnea actual.

public class EjemploArchivo {

public static void main(String[] args) {

JOptionPane.showMessageDialog(null, "Iniciaremos escribiendo un archivo.\nNombre el


archivo con su nmero de carnet");
escribirArchivo();

JOptionPane.showMessageDialog(null, "Ahora leeremos el archivo creado.\nElija el


nombre del archivo recin creado");
leerArchivo();
}

public static void leerArchivo() {


JOptionPane.showMessageDialog(null, "Ejemplo leer archivo");

//Se crea el filtro de archivos


FileNameExtensionFilter filtro = new FileNameExtensionFilter("Archivos de texto",
"txt");

//El objeto Swing que mostrar la ventana para seleccionar el archivo


JFileChooser seleccionador = new JFileChooser();
seleccionador.setFileFilter(filtro);
seleccionador.setDialogTitle("Abrir");

//Muestra la ventana de dilogo


seleccionador.showOpenDialog(null);

if (seleccionador.getSelectedFile() != null) {
File nombreArchivo = seleccionador.getSelectedFile();

Scanner flujoEntrada = null;

try {
flujoEntrada = new Scanner(nombreArchivo);
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "Error al intentar abrir el archivo" +
nombreArchivo);

System.exit(0);
}

JOptionPane.showMessageDialog(null, "Obteniendo el contenido del archivo");

while (flujoEntrada.hasNextLine()) {
String line = flujoEntrada.nextLine();
JOptionPane.showMessageDialog(null, line);
}

flujoEntrada.close();
}

...

Ejercicios
1.

Modifique el programa de ejemplo para que las opciones de lectura y escritura sean accesibles desde un JFrame. El
JFrame deber tener un cuadro de dilogo en el que se debe mostrar la ruta del archivo utilizado para la opcin que
corresponda y un botn para cada opcin.

2.

Modifique el programa para que el texto que se escriba y lea del archivo, pueda ser editado/mostrado en una tabla
(Jtable).

3.

Cree una aplicacin que permita abrir un archivo de Excel, muestre el contenido en una tabla (JTable) y actualice el
contenido del archivo a partir de las modificaciones realizadas en el formulario.

4.

Cree una aplicacin similar a la descrita en el numeral anterior, que permita abrir y editar el contenido de archivos
en formato csv.

Conexin a una base de datos

Nombre:

Mantenimiento de productos

Autor:

PRN315

Descripcin:

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 travs de una consulta inicial.
3. El Administrador desea realizar una bsqueda de archivos, se realiza la seccin Buscar.
4. El Administrador desea modificar uno de los producto, se realiza la seccin Actualizar
5. El Administrador desea ingresar un producto nuevo, se realiza la seccin Ingresar nuevo
6. El Administrador desea eliminar un producto, se realiza la seccin Eliminar
Flujos alternativos:
Postcondiciones:

Seccin: Buscar
1. El Administrador ingresa el/los criterio/s de bsqueda (cdigo y nombre) y presiona el botn 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.

Seccin: 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 botn actualizar.
4. El registro fue actualizado satisfactoriamente. El sistema actualiza el registro en la tabla.
Cursos alternativos:
4. Ocurri un error al modificar el registro. El sistema muestra un mensaje de error.

Seccin: Ingresar nuevo


1. Los controles del formulario se encuentra vacos. El Administrador llena los campos del formulario: Cdigo,
Nombre, Cantidad en existencia y Precio unitario, y presiona el botn 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 informacin de un producto previamente seleccionado. El Administrador presiona el botn
Nuevo.
1.2 El sistema limpia los controles.
2. Ocurri un error al guardar el registro. El mensaje muestra un mensaje de error.

La interfaz de usuario que corresponde al caso de uso descrito deber tener la siguiente forma:

10

Para los campos Cantidad en existencia y Precio unitario usaremos controles de tipo JFormattedTextField. Utilice los
siguiente nombres de los controles:

11

NOMNBRE

TIPO DE
COMPONENTE

DESCRIPCION

btnBuscar

JButton

El botn que disparar el evento clic que generar la bsqueda de los


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

btnElimina

JButton

El botn que disparar el evento clic que generar la eliminacin de los


productos seleccionados en la tabla.

btnGuardar

JButton

El botn que disparar el evento clic que guardar los datos ingresados en los
campos de la seccin Mantenimiento.

btnNuevo

JButton

El botn que limpiar el control del cdigo del producto cuando ya se haya
seleccionado un producto de la tabla.

lBusqCod

JLabel

Label (etiqueta) que corresponde al campo de bsqueda por el cdigo del


producto.

lBusqNombre

JLabel

Label (etiqueta) que corresponde al campo de bsqueda por el nombre del


producto.

lCantidadExist

JLabel

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


producto.

lCodigo

JLabel

Label (etiqueta) que corresponde al campo Cdigo del producto.

lNombre

JLabel

Label (etiqueta) que corresponde al campo Nombre del producto.

lPrecioUnit

JLabel

Label (etiqueta) que corresponde al Precio unitario del producto.

scrollNombreProd

JScrollPane

Scroll (Barra de desplazamiento) vinculado al cuadro de rea de texto del


nombre del producto.

scrollTablaProd

JScrollPane

Scroll (Barra de desplazamiento) vinculado la tabla.

tablaProductos

JTable

Tabla de producto.

txtBusqCodigo

JTextField

Cuadro de texto para el criterio de bsqueda Cdigo del producto.

txtBusqNombre

JTextField

Cuadro de texto para el criterio de bsqueda Nombre del producto.

txtCant

JFormattedTextField

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


producto.

txtCodigo

JTextField

Cuadro de texto para la captura del Cdigo del producto.

txtNombre

JTextField

Cuadro de texto para la captura del Nombre del producto.

txtPrecio

JFormattedTextField

Cuadro de texto con formato para la captura del Precio unitario del producto.

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

12

Crearemos primero las clases que darn soporte al modelo de datos de la tabla.

package prn315.guia11.ejemplosbd.registrarusuario;

public class Producto {

String codigo;
String nombre;
Double cantidadExistencia;
Double precioUnitario;

13

package prn315.guia11.ejemplosbd.registrarusuario;

import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;

public class ProductoTableModel extends AbstractTableModel{

List<Producto> productos = new ArrayList<Producto>();

@Override
public int getRowCount() {
return productos.size();
}

@Override
public int getColumnCount() {
return 4;
}

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Producto producto = productos.get(rowIndex);
Object valor = null;

switch(columnIndex){
case 0: valor = producto.codigo;
break;
case 1: valor = producto.nombre;
break;
case 2: valor = producto.cantidadExistencia;
break;
case 3: valor = producto.precioUnitario;
}

return valor;
}
}

Ahora modificaremos el cdigo generado por NetBeans cuando creamos el formulario.

14

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

public class MantenimientoProductos extends javax.swing.JFrame {

public ProductoTableModel productoTModel = new ProductoTableModel();

/**
* Creates new form DatosPersonales
*/
public MantenimientoProductos() {
initComponents();
}
...

Ahora podemos vincular la instancias de ProductoTableModel, que hemos llamado productoTModel como el modelo de la
tabla.

15

Ahora debemos inicializar los encabezados de las columnas y asignar el ColumnModel a la tabla. Haremos esto en un
mtodo llamado iniciarlizarColumnas, que invocaremos desde el constructor del formulario.

16

...
public MantenimientoProductos() {
initComponents();

inicializarColumnas();
}

private void inicializarColumnas() {


TableColumnModel tColumnModel = new DefaultTableColumnModel();

for (int i = 0; i < 4; i++) {


TableColumn col = new TableColumn(i);

switch (i) {
case 0:
col.setHeaderValue("Cdigo");
break;
case 1:
col.setHeaderValue("Nombre");
break;
case 2:
col.setHeaderValue("Existencia");
break;
case 3:
col.setHeaderValue("Precio");
}

tColumnModel.addColumn(col);
}
tablaProductos.setColumnModel(tColumnModel);
}
...

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

17

Ahora iniciaremos por llenar la tabla con los datos ledos desde la base de datos.
Verifique que el gestor de base de datos PostgreSQL est instalado en su equipo. Si no lo est, descarguelo de esta direccin
http://www.postgresql.org.es/descargas y realice la instalacin.
A travs de pgAdminIII, cree un usuario de base de datos llamado prn315. Posteriormente, cree una base de datos con el
mismo nombre y haga que el usuario recin creado, sea el dueo de la base de datos.

18

Restaure el backup que se encuentra en el aula virtual sobre la base de datos recin creada.
Una vez que tenemos la base de datos, podemos proceder a la configuracin de la aplicacin y la programacin del cdigo
necesario para conectarnos a la base de datos.
Para ello, agregaremos el driver (manejador) de conexin a la base de datos PostgreSQL. Para ello, haga clic derecho en el
nodo Libraries del proyecto, y elija Add Library.

Seleccione el Driver de PostgreSQL que viene integrado con NetBeans y haga clic en el botn Add Library.

19

Ahora, agregaremos un atributo que llamaremos Conexion al formulario, de tipo Connection, provisto por el Driver de
conexin que hemos agregado al proyecto.
Adems, programaremos los mtodos conectar y consultaInicial, que nos permitirn 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 mtodo esttico getConnection, que es el que permite realizar la conexin a la base de datos.
Este es un mtodo sobrecargado que tiene la siguientes formas:

Mtodos relevantes
static Connection getConnection(String url)
Permite establecer una conexin a la base de datos que corresponde a la URL especificada.
static Connection getConnection(String url, Properties info)
Permite establecer una conexin a la base de datos que corresponde a la URL especificada con
las propiedades especificadas en el parmetro info.
static Connection getConnection(String url, String user, String password)
Permite establecer una conexin a la base de datos que corresponde a la URL especificada, con
el usuario y clave especificados.

Usaremos la tercera forma para establecer la conexin a la base de datos.


Antes crearemos un atributo que servir para hacer referencia al objeto conexin que crearemos, que nos permitir que la
conexin pueda ser accedida desde cualquier mtodo de la clase.

20

public class MantenimientoProductos extends javax.swing.JFrame {

public ProductoTableModel productoTModel = new ProductoTableModel();


private Connection conexion;

/**
* Creates new form DatosPersonales
*/
public MantenimientoProductos() {
initComponents();

inicializarColumnas();
conectar();
consultaInicial();
}

...

private void conectar() {


try {
conexion =
DriverManager.getConnection("jdbc:postgresql://localhost:5432/prn315", "prn315", "prn315");

} catch (SQLException ex) {


Logger.getLogger(MantenimientoProductos.class.getName()).log(Level.SEVERE, null,
ex);
}
}

La consulta inicial ser 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 travs de los cuales podemos ejecutar las sentencias SQL. Entre los
mtodos ms relevantes de la clase Connection estn:

21

Mtodos relevantes
void close()
Libera el objeto de conexin 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 generar 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 parmetro.

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 algn valor como parmetro.
Ahora debemos saber como recuperar los datos que devolver la sentencia SQL. Para ello, consultaremos los mtodos ms
relevantes de la clase Statement

Mtodos relevantes
boolean execute(String sql)
Ejecuta la sentencia SQL recibida , que puede devolver mltiples resultados.
ResultSet executeQuery(String sql)
Ejecuta la consulta SQL recibida, que puede devolver un nico 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 ningn 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 manipularamos
una matriz de datos o una tabla.

22

Al consultar el API de la clase ResultSet, encontramos los siguientes mtodos, como los ms importantes.

Mtodos relevantes
Date getDate(int columnIndex)
Devuelve el valor de la columna indicada por el parmetro en la fila actual del objeto, como un
tipo java.sql.Date
double getDouble(int columnIndex)
Devuelve el valor de la columna indicada como parrmetro en la fila actual del objeto, como un
tipo double.
float getFloat(int columnIndex)
Devuelve el valor de la columna indicada como parrmetro en la fila actual del objeto, como un
tipo float.
int getInt(int columnIndex)
Devuelve el valor de la columna indicada como parrmetro en la fila actual del objeto, como un
tipo int.
long getLong(int columnIndex)
Devuelve el valor de la columna indicada como parrmetro en la fila actual del objeto, como un
tipo long.
String getString(int columnIndex)
Devuelve el valor de la columna indicada como parrmetro en la fila actual del objeto, como un
tipo String.
boolean last()
Mueve el cursor (el cursor del ResultSet) a la ltima fila del ResultSet. Devuelve true si la fila en
la que se posiciona el cursor es vlida, false si no hay filas.
boolean next()
Mueve el cursor una fila hacia adelante desde la posicin actual en el ResultSet. Devuelve true si
la fila en la que se posiciona el cursor es vlida, false si no hay ms filas.
boolean previous()
Mueve el cursor una fila hacia atrs en el objeto ResultSet. Devuelve true si la fila en la que se
posiciona el cursor es vlida, false si no hay ms filas.

23

private void consultaInicial() {


try {
String sentenciaSql = "SELECT * FROM producto";
Statement statement = this.conexion.createStatement();

ResultSet resultado = statement.executeQuery(sentenciaSql);

while (resultado.next()) {
Producto producto = new Producto();

producto.codigo = resultado.getString("codigo");
producto.nombre = resultado.getString("nombre");
producto.cantidadExistencia = resultado.getDouble("cantidad_existencia");
producto.precioUnitario = resultado.getDouble("precio_unitario");

this.productoTModel.productos.add(producto);
}

tablaProductos.repaint();

} catch (SQLException ex) {


JOptionPane.showMessageDialog(this, "Error al recuperar los productos de la base
de datos");
ex.printStackTrace();
}
}
...

Al ejecutar el formulario veremos que la tabla ahora tendr los datos que se encuentran almacenados en la tabla producto de
la base de datos prn315.
Ntese 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.
Programaremos ahora la accin para el evento clic del botn Buscar.

24

private void btnBuscarActionPerformed(java.awt.event.ActionEvent evt) {

productoTModel.productos.clear();

try {
PreparedStatement statement = null;

String codigo = txtBusqCodigo.getText();


String nombre = txtBusqNombre.getText();

String sentenciaSql = "SELECT * FROM producto ";

if (!codigo.isEmpty()) {
if (!nombre.isEmpty()) {
sentenciaSql += "WHERE codigo ILIKE ? OR nombre ILIKE ?";
statement = this.conexion.prepareStatement(sentenciaSql);
statement.setString(1, codigo + "%");
statement.setString(2, "%" + nombre + "%");
} else {
sentenciaSql += "WHERE codigo ILIKE ? ";
statement = this.conexion.prepareStatement(sentenciaSql);
statement.setString(1, codigo + "%");
}
} else {
if (!nombre.isEmpty()) {
sentenciaSql += "WHERE nombre ILIKE ?";
statement = this.conexion.prepareStatement(sentenciaSql);
statement.setString(1, "%" + nombre + "%");
} else {
statement = this.conexion.prepareStatement(sentenciaSql);
}
}

25

ResultSet resultado = statement.executeQuery();

while (resultado.next()) {
Producto producto = new Producto();

producto.codigo = resultado.getString("codigo");
producto.nombre = resultado.getString("nombre");
producto.cantidadExistencia = resultado.getDouble("cantidad_existencia");
producto.precioUnitario = resultado.getDouble("precio_unitario");

productoTModel.productos.add(producto);
}

scrollTablaProd.setViewportView(tablaProductos);
tablaProductos.repaint();

} catch (SQLException ex) {


JOptionPane.showMessageDialog(this, "Error al recuperar los productos de la base
de datos");
ex.printStackTrace();
}
}
...

Puede observarse que dependiendo de los valores de los campos de bsqueda, 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 bsqueda.
Si ambos campos tienen valor, la consulta resultante ser 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 condicin (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
despus la tabla sea redibujada en el formulario.
Programaremos ahora el botn Eliminar seleccionados. Por defecto, la tabla tiene un comportamiento que permite la
mltiple seleccin de filas. Necesitamos ahora un mtodo que nos devuelva esas filas seleccionadas.

26

Mtodos relevantes
void clearSelection()
Deshace la seleccin todos las filas y columnas que hayan sido seleccionadas
int getSelectedColumn()
Devuelve el ndice de la primera columna seleccionada, -1 si ninguna columna ha sido
seleccionada.
int getSelectedColumnCount()
Devuelve el nmero de columnas seleccionadas
int[] getSelectedColumns()
Devuelve los indices de todas las columnas seleccionadas.
int getSelectedRow()
Devuelve el ndice de la primera fila seleccionada, -1 si ninguna fila ha sido seleccionada.
int getSelectedRowCount()
Devuelve el nmero 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 parmetro, o -1 si el resultado
est fuera del intervalo [0, getRowCount() -1]

27

private void btnEliminarActionPerformed(java.awt.event.ActionEvent evt) {

//Indices de las filas seleccionadas


int[] indices = tablaProductos.getSelectedRows();
List<Producto> aEliminar = new ArrayList<Producto>();

for (int i : indices) {


Producto producto = productoTModel.productos.get(i);

String sentenciaSql = "DELETE FROM producto WHERE codigo = ?";

aEliminar.add(producto);

try {
PreparedStatement prepStat = conexion.prepareStatement(sentenciaSql);
prepStat.setString(1, producto.codigo);

prepStat.executeUpdate();
} catch (SQLException ex) {
Logger.getLogger(MantenimientoProductos.class.getName()).log(Level.SEVERE,
null, ex);
}
}

productoTModel.productos.removeAll(aEliminar);
scrollTablaProd.setViewportView(tablaProductos);
tablaProductos.repaint();
}
...

Ntese que hemos usado en este caso un PreparedStatement en sustitucin de un Statement. Como puede consultarse en la
tabla de mtodos de la clase Connection, un PreparedStatement es un Statement que admite parmetros para ser sustituidos
en la consulta.

28

Mtodos 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 parmetro indicado por el parameterIndex, el valor double especificado.
void setFloat(int parameterIndex, float x)
Asigna al parmetro indicado por el parameterIndex, el valor float especificado.
void setInt(int parameterIndex, int x)
Asigna al parmetro indicado por el parameterIndex, el valor int especificado.
void setLong(int parameterIndex, long x)
Asigna al parmetro 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 seccin
Mantenimiento y luego presionar el botn 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 insercin.
La sentencia SQL de insercin utilizada tendr la siguiente forma: INSERT INTO producto(codigo, nombre,
cantidad_existencia, precio_unitario) VALUES(producto.codigo, producto.nombre, producto.cantidadExistencia,
producto.precioUnitario), 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 parntesis. Los valores
especificados deben corresponderse con los nombres de los campos en la lista de atributos de la tabla.

29

private void btnGuardarActionPerformed(java.awt.event.ActionEvent evt) {


try {
Producto producto = new Producto();

producto.codigo = txtCodigo.getText();
producto.nombre = txtNombre.getText();
producto.cantidadExistencia = Double.parseDouble(txtCant.getText());
producto.precioUnitario = Double.parseDouble(txtPrecio.getText());

String sentenciaSql = "INSERT INTO producto(codigo, nombre, cantidad_existencia,


precio_unitario) VALUES "
+ "(?,?,?,?)";

PreparedStatement preparedStatement = conexion.prepareStatement(sentenciaSql);


preparedStatement.setString(1, producto.codigo);
preparedStatement.setString(2, producto.nombre);
preparedStatement.setDouble(3, producto.cantidadExistencia);
preparedStatement.setDouble(4, producto.precioUnitario);

preparedStatement.execute();

productoTModel.productos.add(producto);

scrollTablaProd.setViewportView(tablaProductos);
tablaProductos.repaint();
} catch (SQLException ex) {
JOptionPane.showMessageDialog(this, "Error al guardar el producto");
ex.printStackTrace();
}
}
...

Programaremos ahora el evento en la tabla, que nos permita saber el producto que el usuario desea modificar. La
descripcin del caso de uso establece que cuando el usuario desee modificar un producto, deber hacer doble clic en la fila
del producto de su inters.
Ahora deberemos encontrar una forma de saber cuando se trata de un registro nuevo (insercin) y cuando se trata de un
registro ya existente (actualizar). Es lgico que cuando no se haya seleccionado ningn producto de la tabla, el formulario se
encontrar en modo insercin, y que si se ha seleccionado un producto, se encontrar en modo actualizacin.
Para ello usaremos 2 atributos de control. El primero guardar de tipo boolean, nos permitir saber cuando el rea de
30

Mantenimiento del formulario se encuentra en modo de insercin y cuando en modo de actualizacin.


Para saber cual producto ha seleccionado el usuario, programaremos el evento mouseClicked de la tabla, que nos permitir
saber cual es la fila seleccionada y por lo tanto, el producto seleccionado.
Una vez seleccionado el producto, los controles del rea Mantenimiento debern ser llenados con los valores del producto
seleccionado. Y una vez llenados, el usuario podr modificarlos para su posterior actualizacin en la base de datos.
Usaremos el mismo botn para este efecto. El segundo atributo de control ser entonces un objeto de tipo Producto, que
permita guardar el ltimo producto seleccionado.
public class MantenimientoProductos extends javax.swing.JFrame {

public ProductoTableModel productoTModel = new ProductoTableModel();


private Connection conexion;
private boolean guardar = true;
private Producto productoActual;

...

private void tablaProductosMouseClicked(java.awt.event.MouseEvent evt) {


int clics = evt.getClickCount();
int row = tablaProductos.rowAtPoint(evt.getPoint());

if (clics == 2) {
Producto p = productoTModel.productos.get(row);
productoActual = p;

txtCodigo.setText(p.codigo);
txtNombre.setText(p.nombre);
txtCant.setText(String.valueOf(p.cantidadExistencia.doubleValue()));
txtPrecio.setText(String.valueOf(p.precioUnitario.doubleValue()));

guardar = false;
}
}

Ntese al hacer guarde= false, estamos indicando que el formulario ya no se encuentra en modo de edicin.

31

private void btnGuardarActionPerformed(java.awt.event.ActionEvent evt) {


try {
if (guardar) {
Producto producto = new Producto();

producto.codigo = txtCodigo.getText();
producto.nombre = txtNombre.getText();
producto.cantidadExistencia = Double.parseDouble(txtCant.getText());
producto.precioUnitario = Double.parseDouble(txtPrecio.getText());

String sentenciaSql = "INSERT INTO producto(codigo, nombre,


cantidad_existencia, precio_unitario) VALUES "
+ "(?,?,?,?)";

PreparedStatement preparedStatement =
conexion.prepareStatement(sentenciaSql);
preparedStatement.setString(1, producto.codigo);
preparedStatement.setString(2, producto.nombre);
preparedStatement.setDouble(3, producto.cantidadExistencia);
preparedStatement.setDouble(4, producto.precioUnitario);

preparedStatement.execute();

productoTModel.productos.add(producto);
} else {
String sentenciaSql = "UPDATE producto SET nombre = ?, cantidad_existencia =
?, precio_unitario = ? WHERE codigo = ?";

32

PreparedStatement preparedStatement =
conexion.prepareStatement(sentenciaSql);
preparedStatement.setString(1, txtNombre.getText());
preparedStatement.setDouble(2, Double.valueOf(txtCant.getText()));
preparedStatement.setDouble(3, Double.parseDouble(txtPrecio.getText()));
preparedStatement.setString(4, txtCodigo.getText());

preparedStatement.executeUpdate();

productoActual.cantidadExistencia = Double.parseDouble(txtCant.getText());
productoActual.codigo = txtCodigo.getText();
productoActual.nombre = txtNombre.getText();
productoActual.precioUnitario = Double.parseDouble(txtPrecio.getText());
}

scrollTablaProd.setViewportView(tablaProductos);
tablaProductos.repaint();
} catch (SQLException ex) {
JOptionPane.showMessageDialog(this, "Error al guardar el producto");
ex.printStackTrace();
}
}
...

Programaremos ahora el botn Nuevo, que permite quitar la referencia a cualquier producto que se haya seleccionado
previamente e indicar el formulario que entrar en un modo de insercin.
private void btnNuevoActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:

txtCodigo.setText("");
guardar = true;
productoActual = null;
}
...

Si la configuracin regional del Sistema Operativo que est utilizando est configurado con formato de nmeros europeo.
Esto generar un error al intentar actualizar un producto.
La forma ms simple de resolver esto, es agregando las variables de entorno de la mquina virtual de Java (JVM), que le
indiquen a Java que la configuracin regional de nuestra aplicacin debe ser la siguiente:

33

Regin: SV (El Salvador)


Idioma: ES (Espaol)
Para ello, haga clic derecho en el nodo principal del proyecto (en el Navegador de proyectos) y seleccione la opcin
Properties (propiedades).
En la ventana desplegada, elija la opcin Run y en el campo VM Options (Opciones VM), ingrese los valores:
-Duser.language=ES -Duser.region=SV

Cuando se hace una conexin a una base de datos, se crea una conexin directa entre el equipo desde el que se est
realizando la conexin y el servidor de la base de datos.
Para evitar que la base de datos mantenga la conexin abierta en espera de nuevas solicitudes, nuestro programa debe
asegurarse de cerrar la conexin cuando termine su ejecucin. Para ello, programaremos el evento formWindowClossing,
que como su nombre lo indica, ser lanzado cuando el formulario se est cerrando.
Para crear el evento, haga clic derecho sobre el formulario que hemos creado (en un rea donde no haya otro control), elija
la opcin Events del men contextual, elija la opcin Window y luego windoCclosing. NetBeans generar el mtodo
escuchador del evento, y en l agregaremos el cdigo necesario para cerrar la conexin a la base de datos.

34

private void formWindowClosing(java.awt.event.WindowEvent evt) {


// TODO add your handling code here:
try {
conexion.close();
} catch (SQLException ex) {
JOptionPane.showMessageDialog(this, "Ocurri un error al cerrar la conexin a la
base de datos");
}
JOptionPane.showMessageDialog(this, "La conexin a la base de datos ha sido
cerrada");
}

35

Ejercicios
1.

Agregue a la aplicacin de ejemplo el cdigo necesario para resolver el caso de uso: Registrar venta.

2.

Cree una aplicacin que permita administrar los datos de las tiendas (lugares de venta) de una empresa, los
departamentos en los que est dividida cada tienda (departamento de nios, nias, electrnicos, etc.) y los
empleados que trabajan en cada tienda. Restaure el archivo ejercicio_tienda.backup para tener una base de datos
para poder trabajar.

36

Anda mungkin juga menyukai