SQL Server: 5 Scripts utiles entrega I

A continuación muestro un conjunto de sentencias de SQL server que me han resultado muy interesantes y por supuesto muy útiles. Son scripts muy sencillos pero veras que te resultaran muy útiles si ha diario haces desarrollos con bases de datos, ho igual los puedes tener como referencia por si en algún momento los necesitas.

A continuación muestro el script que use para crear la tabla usada en los scripts.

CREATE TABLE [dbo].[tbl_usuarios](
	[id_Usuario] [bigint] IDENTITY(1,1) NOT NULL,
	[tx_nombre1] [varchar](30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
	[tx_correo] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
	[tx_genero] [varchar](20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
 CONSTRAINT [PK_tbl_usuarios] PRIMARY KEY CLUSTERED 
(
	[id_Usuario] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

A continuacion insertamos algunos datos (ficticios) de ejemplo:

INSERT tbl_usuarios (tx_nombre1,tx_correo,tx_genero)
	VALUES ('xavier' ,'xav13r_123@gmail.com' ,'masculino');
INSERT tbl_usuarios (tx_nombre1,tx_correo,tx_genero)
	VALUES ('itzel' ,'itzel5319@gmail.com' ,'femenino');
INSERT tbl_usuarios (tx_nombre1,tx_correo,tx_genero)
	VALUES ('daniel' ,'daniil26@gmail.com' ,'masculino');
INSERT tbl_usuarios (tx_nombre1,tx_correo,tx_genero)
	VALUES ('america' ,'america5319@gmail.com' ,'femenino');
INSERT tbl_usuarios (tx_nombre1,tx_correo,tx_genero)
	VALUES ('gonzalo' ,'gonzasilve@gmail.com' ,'masculino');
INSERT tbl_usuarios (tx_nombre1,tx_correo,tx_genero)
	VALUES ('michel' ,'michl5173@gmail.com' ,'femenino');

En este caso no hemos especificado el valor del dato id_usuario porque el dbms lo genera de manera automatica. Como se puede observar los datos que acabamos de insertar son los siguientes:

id_Usuario           tx_nombre1      tx_correo                        tx_genero
-------------------- --------------- --------------------------------- --------------------
1                    xavier          xav13r_123@gmail.com              masculino
2                    itzel           itzel5319@gmail.com               femenino
3                    daniel          daniil26@gmail.com                masculino
4                    america         america5319@gmail.com             femenino
5                    gonzalo         gonzasilve@gmail.com              masculino
6                    michel          michl5173@gmail.com               femenino

(6 filas afectadas)

Resetear campo auto incrementable

La siguiente sentencia permite establecer el siguiente valor a generarse en un campo tipo auto incrementable. Por ejemplo, si queremos que la siguiente vez que insertemos un registro en la tabla (tbl_usuarios), el id_usuario que se genere sea el 10, entonces escribimos:

DBCC CHECKIDENT('tbl_Usuarios', RESEED, 9) ;

--...respuesta del dbms:
--  Comprobación de información de identidad: valor de identidad actual '6', valor de columna actual '9'.
--  Ejecución de DBCC completada. Si hay mensajes de error, consulte al administrador del sistema.

Ahora para comprobar, insertamos otro registro mas:

INSERT tbl_usuarios (tx_nombre1,tx_correo,tx_genero)
	VALUES ('Patricia' ,'patygml53@gmail.com' ,'femenino');
--Hacemos una consulta de todos los registros:
select * from tbl_usuarios;

Podemos observar que el id del nuevo registro ha sido el que queriamos (el 10):

id_Usuario           tx_nombre1      tx_correo                        tx_genero
-------------------- --------------- --------------------------------- --------------------
1                    xavier          xav13r_123@gmail.com              masculino
2                    itzel           itzel5319@gmail.com               femenino
3                    daniel          daniil26@gmail.com                masculino
4                    america         america5319@gmail.com             femenino
5                    gonzalo         gonzasilve@gmail.com              masculino
6                    michel          michl5173@gmail.com               femenino
10                   Patricia        patygml53@gmail.com               femenino

(7 filas afectadas)

Esta instrucción es muy útil por ejemplo cuando borramos registros y deseamos que los id de los nuevos registros sigan siendo consecutivos.

Obtener el ultimo Id insertado en una tabla

A veces, cuando estamos escribiendo un programa, necesitamos saber cual es el ultimo id mas alto que se ha insertado o generado dentro de una tabla. El siguiente script te permite obtener dicho dato.

--Forma 1
select IDENT_CURRENT('tbl_usuarios') as i_UltimoId

--Forma 2
select top 1 id_usuario as i_UltimoId from tbl_usuarios
order by id_usuario desc

Como puedes ver la primera forma es a través de la funcion IDENT_CURRENT que SQL Server trae incluida. Usala cuando tengas la seguridad de que no has borrado registros y todos sean consecutivos. La segunda forma en si, solo ordena de mayor a menor (descendente) a la tabla por una columna y hace un top 1 (toma solo una fila) de esa misma columna, obviamente que de antemano debemos saber que columna es la llave primaria; en este caso es la columna id_usuario. Para ambas formas el resultado es el que se muestra a continuacion:

i_UltimoId
--------------------
10

(1 filas afectadas)

Ojo! La funcion IDENT_CURRENT() siempre devuelve el valor actual generado en el campo identidad (llave primaria), de modo que si borramos el registro con id 10 (Patricia) y ejecutamos la instruccion IDENT_CURRENT ésta sigue devolviendo 10 y no 6 como tal vez esperarias. Si quieres que devuelva 6 entonces resetea con la instrucción:

DBCC CHECKIDENT('tbl_Usuarios', RESEED, 6) ;

¿Lo captaste?

Respaldar un tabla creando otra (SELECT-INTO)

Yo le llamo respaldar, pero tu le puedes decir como gustes (por ej. copiar). El punto es que esta forma de crear una nueva tabla es una combinacion de una sentencia insert y una sentencia select. Si quisieramos respaldar todos los datos de la tabla tbl_usuarios, lo hacemos con la siguiente instruccion:

SELECT *
INTO tbl_usuarios_respaldo
FROM tbl_usuarios

Despues de ejecutar la instruccion anterior se ha creado una nueva tabla llamada tbl_usuarios_respaldo exactamente con los mismos datos que la tabla tbl_usuarios. Si gustas, en la parte del select puedes especificar solo las columnas que necesites respaldar. Por ejemplo:

SELECT tx_nombre1, tx_genero
INTO tbl_usuarios_respaldo2
FROM tbl_usuarios

Solo estamos respaldando los campos nombre y genero. Por lo que la tabla tbl_usuarios_respaldo2 tendra solo las columnas indicadas:

tx_nombre1                     tx_genero
------------------------------ --------------------
xavier                         masculino
itzel                          femenino
daniel                         masculino
america                        femenino
gonzalo                        masculino
michel                         femenino
Patricia                       femenino

(7 filas afectadas)

En el script que mostrare a continuación vamos a aprovechar esta misma instrucción para copiar la estructura de una tabla y crear una tabla vacía.

Insertar en una tabla datos de otra tabla (INSERT-SELECT)

Este script te permitirá insertar datos en una tabla pero tomando los datos (a insertar) de otra tabla, con un select. En otras palabras, la forma normal de hacer una insercion en una tabla es especificando los datos con la clausula values. Aqui te muestro otra forma de hacer una insercion, en vez de especificar los datos, especificas una consulta (clausula SELECT) que devolvera los datos que deseas insertar.

Cabe mencionar que la tabla donde se va hacer el INSERT debe existir, venga pues vamos a crearla, escribe el siguiente script y ejecutalo en el dbms:

SELECT id_usuario, tx_nombre1 as tx_nombre,tx_correo as tx_email, tx_genero
INTO tbl_usuarios2
FROM tbl_usuarios
where 1=2

…Nos la hemos ingeniado para crear una tabla vacia; agregamos una condicion que nunca se cumplira (observa la clausula WHERE) y por lo tanto la sentencia anterior solo creara la tabla pero sin datos (el select no devolvera datos por la condicion que agregamos). También observa como en nuestra nueva tabla he cambiado el nombre a algunos campos.

Bien, sigamos, si deseamos copiar todos los usuarios de sexo femenino en la tabla recien creada (tbl_usuarios2), lo hacemos con el siguiente script:

INSERT INTO tbl_usuarios2  (id_usuario, tx_nombre, tx_email)
  SELECT id_usuario, tx_nombre1, tx_correo
  FROM tbl_usuarios
  WHERE tx_genero='femenino';

Ahora la tabla tbl_usuarios2 contiene los datos devueltos por la consulta que esta de la linea 2-4, es decir, contiene lo siguiente:

id_usuario   tx_nombre         tx_email                       tx_genero
------------- ---------------- ------------------------------ --------------------
1            itzel             itzel5319@gmail.com            femenino
2            america           america5319@gmail.com          femenino
3            michel            michl5173@gmail.com            femenino
4            Patricia          patygml53@gmail.com            femenino

(4 filas afectadas)

Observa como se ha generado el Id automaticamente, lo que comprueba que la estructura de las 2 tablas es la misma.

Actualizar campos de una tabla con los datos de otra tabla (UPDATE-FROM)

Este script es muy similar al anterior pero en vez de hacer un INSERT hace una actualizacion (update). Olvida los ejemplos anteriores. Para efectos de prueba vamos a suponer que los datos de la tabla tbl_usuarios2 estan desactualizados y deseamos atualizarlos con datos actualizados, los cuales estan en la tabla tbl_usuarios.

Suponiendo que el Id coincide en ambas tablas. El siguiente script realiza la actualización del nombre y el correo electrónico:

update tbl_usuarios2
set tbl_usuarios2.[tx_nombre]	= tbl_usuarios.[tx_nombre1],
 tbl_usuarios2.[tx_email]		= tbl_usuarios.[tx_correo] 
from tbl_usuarios, tbl_usuarios2
where tbl_usuarios.id_usuario = tbl_usuarios2.id_usuario

…Eso es todo por ahora. Próximamente estaré exponiendo mas ejemplos de SQL; ejemplos que a mi me han sido útiles en proyectos personales y en mis actividades diarias de la oficina.

…y recuerda que siempre es mejor CTRL+N que CTRL+C. Lo que te intento decir es que si realmente quieres aprender no hay nada como practicarlo escribiendo todo y no copiando. Dejame un comentario si te gusto o sirvió ¿vale?, igualmente si tuve algún error tipográfico.

Gracias por tu visita. Saludos cordiales.

JQuery UI: Como usar el control Tab con MySql

JQuery UI Logo

En esta ocasión quiero presentar a la librería JQuery UI y para esto he diseñado un sencillo ejemplo que básicamente despliega dos tablas de MySql; al dar click en una pestaña (tab) se muestra una tabla, al elegir la otra se muestra el contenido de otra segunda tabla.

¿Que es JQuery UI?

En resumen, JQuery UI es un subconjunto del FrameWork JQuery y fue creado para añadir nuevas y complejas funcionalidades a ésta. Este conjunto de nuevas funcionalidades pueden ser plug-ins, widgets, y efectos visuales (arrastrar, FadeIn, FadeOut, etc.), todos diseñados con la misma filosofía que JQuery; fácil de usar y compatible con los navegadores más populares.

Lo que necesitas para realizar este ejemplo

Para la realizacion de este ejemplo necesitas la siguiente lista de herramientas de desarrollo instaladas en tu computadora. Así que si alguna no la tienes, este el momento ideal para hacerlo:

  • PHP 5 (o superior).
  • Un servidor web (ej. IIS o Apache) que tenga soporte para PHP 5.
  • El FrameWork JQuery.
  • JQuery UI.
  • MySql 5 (o superior).
  • Gusto por aprender.

    • Como puedes ver he puesto un enlace a la página de descarga de cada herramienta. El servidor web puede ser el que tú gustes pero cuida que tenga soporte para reconocer y ejecutar código PHP, en mi caso uso el servidor Apache.

Diseñar la Base de datos en MySql

Para el ejemplo voy a suponer que tenemos una lista de productos organizados en categorías. Es por esto que utilizare una tabla de productos y otra tabla de categorías. Los datos que me interesan guardar sobre los productos son:

  • El nombre del producto.
  • Una breve descripción acerca del producto.
  • La fecha en que caduca el producto.
  • El precio al que se compra con el proveedor.
  • El precio al que se vende al público.
  • La categoría en la que se ha clasificado el producto.

    • Los productos estarán organizados en varias categorías, ejemplos de categorías pueden ser; Carnes frías, Perfumería, Abarrotes, Frituras, etc.
      Para que el ejemplo siga siendo muy sencillo y fácil de entender solo he considerado dos categorías y solamente tendré una lista de 3 productos.

Scripts para crear la base de Datos en MySql

A continuación pongo los scripts que debes usar para crear la base de datos del ejemplo, así como algunas inserciones que he realizado en las dos tablas:

/*Crear la base de datos*/
CREATE DATABASE jquerytabs_mysql;
USE jquerytabs_mysql;

/*Crear la tabla Productos*/
CREATE TABLE tbl_productos(id_producto INT NOT NULL AUTO_INCREMENT,
tx_NombreProducto VARCHAR(50),
tx_Descripcion VARCHAR(500),
dt_FechaCaducidad DATETIME DEFAULT NULL,
mn_PrecioCompra DECIMAL(5,2),
mn_PrecioPublico DECIMAL(5,2),
id_Categoria INT,
primary key(id_producto),
foreign key (id_Categoria) references cta_CategoriasProductos(id_CategoriaProducto)  );
  
/*Crear la tabla de Categorias*/
CREATE TABLE cta_CategoriasProductos(id_CategoriaProducto INT NOT NULL AUTO_INCREMENT,
tx_Nombre VARCHAR(50),
tx_Descripcion VARCHAR(500),
primary key(id_CategoriaProducto) );


/*Insertar 3 Productos de ejemplo*/
INSERT INTO tbl_productos (tx_NombreProducto,tx_Descripcion,dt_FechaCaducidad,mn_PrecioCompra,mn_PrecioPublico,id_Categoria) 
VALUES('Shampoo Ultra humectante','Shampoo caja/2 pzas marca patito','2013-07-04',245.50,315.00,1);

INSERT INTO tbl_productos (tx_NombreProducto,tx_Descripcion,dt_FechaCaducidad,mn_PrecioCompra,mn_PrecioPublico,id_Categoria)
VALUES('Papas refritas','Papas fritas bolsa 150 gr. superpapas','2012-11-22 10:45',3.50,6.50,2);

INSERT INTO tbl_productos (tx_NombreProducto,tx_Descripcion,dt_FechaCaducidad,mn_PrecioCompra,mn_PrecioPublico,id_Categoria)
VALUES('Jabon anti alopecia','Jabon higienico 1 pza 145 gr.','2013-04-16 07:57',8.50,10.50,1);

//Insertar 2 categorias para los productos
INSERT INTO cta_CategoriasProductos(tx_Nombre,tx_Descripcion) 
VALUES('Perfumeria','Todo tipo de productos de limpieza y productos de tocador');

INSERT INTO cta_CategoriasProductos(tx_Nombre,tx_Descripcion) 
VALUES('Frituras','Productos de frituras; palomitas, totopos, etc.');

INSERT INTO cta_CategoriasProductos(tx_Nombre,tx_Descripcion) 
VALUES('Abarrotes','Todo tipo de Productos de abarrotes; enlatados, veladoras, refrescos, etc .');

Con ayuda de algun cliente para MySql como Workbench o el PhpMyAdmin ejecuta los scripts anteriores para recrear la base de datos e insertar los datos de ejemplo. En mi caso he utilizado el Workbench.

Diseño de la pagina web

El diseño es muy sencillo y únicamente consiste de un solo documento HTML en el que se insertara el Widget Tab de JQuery, es muy similar al diseño que muestro a continuación:
Esbozo de la GUI del ejemplo.

Cuando el usuario elija la primera Pestaña se mostrara el contenido de la tabla de productos. En la Pestaña dos se mostrara la tabla de categorías. Existen varias formas de decirle a JQuery de donde debe tomar los datos que mostrara en cada Pestaña, tema que por ahora no tocare para no confundirte. En este caso el contenido de cada pestaña será cargado con ayuda de Ajax.

Vista de la estructura de carpetas y archivos del ejemplo

Para que entiendas mejor los archivos de código fuente que mostrare más adelante, a continuación pongo una imagen donde se observa claramente como he organizado en carpetas los archivos de este ejemplo:
Estructura de carpetas del ejemplo JQuery Tabs

Si observas la imagen te darás cuenta que dentro de la carpeta css hay una carpeta llamada cupertino; este es el nombre del tema que me descargue de JQuery UI, es el que más me gusto (azul claro tipo agua).

El código fuente de estos archivos los iré mostrando uno a uno junto con una breve explicación de la función que tiene cada uno. El orden en que los mostrare es el orden en el que teóricamente el navegador los íra cargando.

El código Fuente de los archivos

Para ver el ejemplo funcionando en el navegador debemos escribir la ruta a la carpeta ejemplo5 que a su vez está dentro de la carpeta jquery, la cual (como se observa en la imagen) es la raíz donde está guardado todo el ejemplo, cuando escribimos dicha URL (http://localhost/jquery/ejemplo5/) en el navegador se desplegara el documento HTML index.html. El código de este archivo lo muestro a continuación:
index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Ejemplo5 con JQuery :: UI Tabs y MySql</title>
	<!--Hoja de estilo-->
	<link rel="StyleSheet" type="text/css" href="../css/cupertino/jquery-ui-1.8.23.custom.css" />
	<link rel="StyleSheet" type="text/css" href="../css/css_ejemplo5.css" />
	
	<!--Archivos de script de JQuery-->
	<script type="text/javascript" src="../js/jquery-1.8.0.min.js"></script>
	<script type="text/javascript" src="../js/jquery-ui-1.8.23.custom.min.js"></script>
	<!--Archivo de script del ejemplo-->
	<script type="text/javascript" src="../js/func_ejemplo5.js"></script>

   </head>
   <body>
	 <br/>
	 
		<TABLE WIDTH="95%" BORDER="0">
			<TR>
				<TD >
				<!-- Widget Tab -->
					<div id="fichass">
						<ul>
							<li><a href="ajax/listarProductos.php">Productos</a></li>
							<li><a href="ajax/listarCategorias.php">Categorias</a></li>
						</ul>
					</div>				
				</TD>
			</TR>
		</TABLE>		

   </body>
</html>

Espero que con la imagen de las carpetas que te mostré anteriormente puedas deducir el porqué de las rutas en las etiquetas para importar las hojas de estilo (LINK), y el porqué de las rutas en las etiquetas para importar los archivos de código JavaScript (SCRIPT). Como se observa el archivo está muy, muy corto, a continuación una breve explicación de las líneas más importantes de este archivo:

En la línea 7 y 8 se están importando dos hojas de estilos; el primer archivo .css (jquery-ui-1.8.23.custom.css) corresponde a la hoja de estilos de JQuery UI, el segundo archivo .css (css_ejemplo5.css) corresponde a una hoja que he creado para darle un poco de presentación a las tablas que mostraran el contenido de las tablas de MySql.

En la línea 11 se importa el Framework JQuery.
En la línea 12 se importa la librería JQuery UI.
En la línea 14 se importa un archivo que he creado para inicializar JQuery y el Widget Tab.

En el cuerpo del documento HTML (BODY) se observa cómo he creado una tabla con una sola fila y una sola columna y dentro de dicha columna e insertado el Widget Tab. El objetivo de la tabla es limitar el ancho que ocupa el Widget dentro del documento HTML.

css_ejemplo5.css
Este archivo es una hoja de estilos que he creado para hacer un RESET del CSS del documento HTML y crear unas cuantas clases para dar presentación a las tablas HTML que muestran los datos de las tablas Productos y Categorías (las tablas se crean en los archivos que se cargan con Ajax). Los archivos listarProductos.php y listarCategorias.php son los que hacen uso de las clases que se crean en este archivo.

@CHARSET "UTF-8";
/******* GENERAL RESET *******/

html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em,
font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody,
 tfoot, thead, tr, th, td {
  border:0pt none;
  font-family:inherit;
  font-size: 100%;
  font-style:inherit;
  font-weight:inherit;
  margin:0pt;
  padding:0pt;
  vertical-align:baseline;
}

.celdaWhite {	background-color: #FFFFFF; }
.celdaGreen {	background-color: #E5FFE9; }

.filaEncabezado  { 
	background-color: #B5B5B5; 
	font-size: 9pt; 
	font-weight: bold; 
	font-family: Verdana, Arial, Helvetica, sans-serif; 
}

td { 
	color: #333333; 
	font-family: 'Comic Sans MS',Verdana, Arial, Helvetica, sans-serif; 
	font-size: 7.5pt; 
	vertical-align:middle;
	padding:3px;
}

En el archivo se observa lo siguiente:
Únicamente he creado 3 clases: celdaWhite, celdaGreen y filaEncabezado.
Asigne estilos para todas las celdas de una tabla HTML (línea 27 a línea 33).

func_ejemplo5.js
Este archivo se encarga de Inicializar el Framework JQuery y de especificar que la capa (DIV) que están dentro del cuerpo del archivo index.php debe convertirse en un Widget Tab:

/*
	Descripcion: 	Inicializacion de JQuery y el Widget Tab.
*/

	var miPagina;
	miPagina=$(document);
	miPagina.ready(inicializarEventos);

	function inicializarEventos()
	{
		var capaFichas = $("#fichass");
		capaFichas.tabs({ collapsible: true });
	}

Si has revisado mis anteriores ejemplos de JQuery te darás cuenta que estoy utilizando la misma sintaxis de siempre para inicializar JQuery. El parámetro collapsible del método tabs() es un valor booleano que indica si el contenido de la pestaña debe ocultarse al dar click en el nombre de la pestaña, en este caso he especificado que sí.

Te explicare un poco que pasa detrás del telón…
Recordemos que el método ready() solo se hace disponible después de que todo el contenido del documento HTML ha sido recibido del servidor, es por eso que dentro de este método he creado un objeto asociado a la capa "fichass" (línea 11) y a través de este objeto le indico a jQuery que a esta capa la convierta en un Widget del tipo Tab (linea 12).

Cuando el método tabs() se ejecuta y detecta que en el parámetro href de los nombres de las pestañas (líneas 26 y 27 de index.html) hay una URL a un archivo, entonces, automáticamente carga el archivo asociado a la primera pestaña a través de Ajax. Léase la documentación del Widget Tab, opción selected aquí.

Si deseáramos que al cargarse el Widget Tab se mostrara por defecto la pestaña 2 entonces deberíamos ejecutar este método con la opción selected: 1. Las fichas se numeran de 0 a n-1, donde n es el numero de pestañas del Widget Tab.

conectar_bd.php
Este archivo se encarga de hacer la conexión al DBMS MySql, o en caso de error, mostrar una descripción del porque no se pudo conectar (función mysql_error de MySql). Este archivo es insertado con la función include de PHP dentro de los archivos listarProductos.php y listarCategorias.php.

<?php
	
$conexio = null;
function conectar_bd() {
	global $conexio;
	//Definir datos de conexion con el servidor MySQL (local)	
	$elUsr = "root";
	$elPw  = "12345";
	$elServer ="localhost";
	$laBd = "jquerytabs_mysql";
	
	//Obtener link de conexion
	$conexio = mysql_connect($elServer, $elUsr , $elPw) or die (mysql_error());
	
	mysql_select_db($laBd, $conexio ) or die (mysql_error());
}
	
?>

Este script PHP en resumen; declara una variable global ($conexio, guardara el link de conexión a la bd) y define una función llamada conectar_bd() la cual al ser invocada hará la conexión a MySql y dejara esa conexión abierta en la variable global anteriormente mencionada.

listarProductos.php
Este archivo es solicitado al servidor a través de Ajax cada vez que se da click en la primera pestaña. Tiene la función de hacer una consulta a la base de datos para obtener los registros de la tabla productos y a través de un ciclo desplegarlos:

<?php
	include("../conectar_bd.php");
	conectar_bd();
	
	//Hacer una consulta de la tabla productos a la base de datos
	$queryProductos = "SELECT tbl_productos.*,cta_CategoriasProductos.tx_Nombre AS categoria 
						FROM tbl_productos
						INNER JOIN cta_CategoriasProductos
						ON tbl_productos.id_Categoria = cta_CategoriasProductos.id_CategoriaProducto;";
	$resProductos = mysql_query($queryProductos);
?>

	<TABLE WIDTH="95%" BORDER="0" >
		<TR class="filaEncabezado">
			<TD width="1%" align="left">ID</TD>
			<TD align="left">NOMBRE</TD>
			<TD align="left">DESCRIPCION</TD>
			<TD align="left">FECHA CADUCIDAD</TD>
			<TD align="left">PRECIO LISTA</TD>
			<TD align="left">PRECIO PUBLICO</TD>
			<TD align="left">CATEGORIA</TD>
		</TR>
<?php	
	$i=0;
	//Ciclo para obtener y desplegar cada registro de la tabla productos
	while( $filaProducto = mysql_fetch_array($resProductos) ) {
		$estilo = ( ($i%2)==0 ) ? "celdaWhite" : "celdaGreen";
?>
		<TR class="<?=$estilo; ?>"  >
			<TD><?=$filaProducto['id_producto']; ?></TD>
			<TD><?=$filaProducto['tx_NombreProducto']; ?></TD>
			<TD><?=$filaProducto['tx_Descripcion']; ?></TD>
			<TD><?=$filaProducto['dt_FechaCaducidad']; ?></TD>
			<TD><?="$".$filaProducto['mn_PrecioCompra']; ?></TD>
			<TD><?="$".$filaProducto['mn_PrecioPublico']; ?></TD>
			<TD><?=$filaProducto['categoria']; ?></TD>
		</TR>
<?php
	$i++;
	}	//Fin de ciclo
?>
	</TABLE>
<?php
	mysql_close($conexio);
?>

Observa como he realizado un match entre la tabla Productos y la tabla de Categorías a través del campo id_Categoria. Este match lo hago para desplegar el nombre de la categoría en vez de su ID; pues al usuario no le interesa el Id, sino el nombre de la categoría en la que se ha clasificado el producto. Si no entiendes muy bien mi consulta de SQL te recomiendo leer acerca de la instrucción INNER JOIN.

En la línea 44 se cierra conexión a la base de datos, misma que se abrió al invocar a la función conectar_bd() en la línea 3.

listarCategorias.php
Este archivo al igual que el archivo listarProductos.php es solicitado al servidor a través de Ajax, pero ahora cuando se da click en la segunda pestaña (Categorias):

<?php
	include("../conectar_bd.php");
	conectar_bd();
	
	//Hacer una consulta de la tabla categorias a la base de datos	
	$queryCategorias = "SELECT * FROM cta_CategoriasProductos; ";
	$resCategorias = mysql_query($queryCategorias);
?>

	<TABLE WIDTH="95%" BORDER="0" >
		<TR class="filaEncabezado">
			<TD width="1%" align="left">ID</TD>
			<TD align="left">NOMBRE</TD>
			<TD align="left">DESCRIPCION</TD>
		</TR>
<?php	
	$i=0;
	//Ciclo para obtener y desplegar cada registro de la tabla categorias
	while( $filaCategoria = mysql_fetch_array($resCategorias) ) {
		$estilo = ( ($i%2)==0 ) ? "celdaWhite" : "celdaGreen";
?>
		<TR class="<?=$estilo; ?>"  >
			<TD><?=$filaCategoria['id_CategoriaProducto']; ?></TD>
			<TD><?=$filaCategoria['tx_Nombre']; ?></TD>
			<TD><?=$filaCategoria['tx_Descripcion']; ?></TD>
		</TR>
<?php
	$i++;
	}	//Fin del ciclo
?>
	</TABLE>
<?php
	mysql_close($conexio);
?>

Como puedes observar en el código, se hace un barrido completo de la tabla Categorías y a través de un ciclo while se mandan al navegador cada uno de los registros.

En la línea 33 se cierra la conexión a la base de datos, misma que se abrió al invocar a la función conectar_bd() en la línea 3.

Screenshots del ejemplo

A continuación muestro pantallazos del ejemplo en el navegador Chrome de Google.
Ficha Productos:
Ejemplo JQuery Tabs en ejecucion; Pestaña productos.
Ficha Categorias;
Ejemplo JQuery Tabs en ejecucion: Pestaña Categorias.

Demo

Si gustas ver el ejemplo en ejecución da Click en este enlace.

 

Eso es todoo, espero que te haya gustado y principalmente que ojalá te sirva. Si deseas el código basta con que dejes tu email y en cuanto vea tu mensaje te hago llegar el ejemplo en un archivo comprimido. Si te gusto el articulo, te invito a que me dejes un comentario, así me motivas a escribir más.

Saludos cordiales.

 
 

Enlaces relacionados:

 
 

Autenticacion de usuarios en PHP y MySql

Hola, mi cuenta de gmail ha sido vulnerada, por lo que las imágenes no se ven, pero esta entrada ya la he replicado en http://www.notas-programacion.com/2014/10/autenticacion-de-usuarios-en-php-y-mysql/, el contenido de este blog se estará migrando progresivamente allá, disculpa las molestias.

Como he visto que es muy solicitado el codigo que publique sobre como autenticar usuarios en java y MySql, decidi publicar esta nueva entrada que esta muy relacionada con dicho tema, pero ahora en PHP y un poquito mas completo; encriptacion del password en MD5.

Como decía anteriormente, en algunos sistemas a veces un requerimiento es que se manejen privilegios y por lo tanto usuarios, esto con el fin de controlar lo que cada usuario puede hacer/ver una vez dentro del sistema. En esta entrada únicamente se muestra como autenticar a los usuarios para entrar al sistema, es decir, cada usuario tendrá los mismos privilegios; aunque la tabla de usuarios de MySql (que mostrare mas adelante) ya incluye un campo que determina el tipo de usuario este campo no sera utilizado por ahora. Sin mas preámbulos muestro el ejemplo…

La base de datos

Como siempre que voi a hacer uso de una BD, empezare mostrando el script para recrear las tablas que usare en el ejemplo:

/* Crear la base de datos */
create database prueba;

/*Crear Catalogo de tipos de usuario */
create table ctg_tiposusuario
(
id_TipoUsuario	int not null auto_increment,
tx_TipoUsuario	varchar(100),
primary key(id_TipoUsuario)
);


/* Catalogo de usuarios */
create table tbl_users(
id_usuario int not null auto_increment,
tx_nombre varchar(50) not null,
tx_apellidoPaterno varchar(50),
tx_apellidoMaterno varchar(50),
tx_correo varchar(100),
tx_username varchar(50),
tx_password varchar(250),
id_TipoUsuario int,
dt_registro datetime,
primary key(id_usuario),
foreign key(id_TipoUsuario) references ctg_TiposUsuario(id_TipoUsuario)
);

/*Insertar tipos de usuarios de prueba*/
INSERT INTO `ctg_tiposusuario`( `tx_TipoUsuario`) VALUES ('Administrador');
INSERT INTO `ctg_tiposusuario`( `tx_TipoUsuario`) VALUES ('Usuario Normal');

/*passwrd: 12345*/
/*Insertar usuario de prueba*/
INSERT INTO tbl_users (tx_Nombre,tx_apellidoPaterno,tx_apellidoMaterno,tx_correo,
tx_username,tx_password,id_TipoUsuario,dt_registro) 
VALUES('Gonzalo','Silverio','Silverio','gonzasilve@gmail.com',
'gonzasilve','827ccb0eea8a706c4c34a16891f84e7b',1,'2012-11-09 17:35:40');

La base de datos que usare se llama prueba. Como se observa unicamente son dos tablas, ademas, he creado un catalogo con los diferentes tipos de usuario que pudiera haber, solo he añadido dos tipos de usuario (Administrador y Usuario normal) a modo de ejemplo, pero se pueden añadir mas. Si observas, inserto un usuario de prueba. Si quieres asignar otro password al usuario de prueba puedes utilizar esta sencilla herramienta que te permite generar un MD5 a partir de una cadena cualquiera: http://shalo.site50.net/obtener_md5.php

Herramientas necesarias

Supongo que para el momento de estar leyendo este articulo ya tienes el software necesario (ho al menos piensas instalarlo). Como he visto que los visitantes muchas veces son estudiantes de carrera ho aficionados a la programacion; pero con poca experiencia (me incluyo), voi a listar las herramientas de sw necesarias que debes tener yá en tu maquina si quieres probar este exquisito codigo :), puedes usar otro servidor y otro dbms, pero yo use estas:
Como ves son pocos requisitos, si no tienes alguno este es el momento para que lo instales. El servidor de correo de hecho es opcional, solo lo instale para hacer pruebas en mi computadora local (una laptop), si tienes dudas sobre hMailServer en la misma pagina viene mucha documentación acerca de como instalarlo y configurarlo. Si tienes más dudas puedes preguntarle al oraculo (google) escribiendo esto ‘hmailserver y php’.

Bueno vamos a lo interesante…

El código fuente

index.php

Este archivo permite mostrar la ventana de Login, en esta como es de suponerse el usuario introduce su nombre de usuario, su password y le da click al boton enviar, bueno muestro el codigo:
<!--     
	Instituto Tecnologico de Zacatepec, Morelos 
Descripcion:   Archivo para mostrar una pantalla de login con los campos;
				de usuario y password, los 2 datos se envian al archivo validarUsuario.php 
				por el metodo POST. 
Author:     Gonzalo Silverio  gonzasilve@gmail.com 
Archivo:    index.php 
-->

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Login ::. Ejemplo autenticar usuarios</title>
	
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<link rel="stylesheet" href="estilos.css" type="text/css">
	<script src="jquery171.js" type="text/javascript"></script> 
	<script src="jquery.validate.js" type="text/javascript"></script>
	<script type="text/javascript" src="jquery.alerts.js"></script>
	<link href="jquery.alerts.css" rel="stylesheet" type="text/css" />
	
	<script type="text/javascript">
	<!--
		$().ready(function() {
			$("#frmlogin").validate();
			$("#usuario").focus();
		});
	// -->
	</script>
	
</head>
<body>
<br /><br />
<form id="frmlogin" name="frmlogin"  method="POST" action="validarUsuario.php">
<table align="center" width="200px">
<tr>
	<td colspan="2" align="center"><h3>Iniciar sesi&oacute;n</h3></td>
</tr>
<tr>
	<td>Usuario</td>
	<td>
		<input type="text" name="usuario" id="usuario" class="required" maxlength="50">
	</td>
</tr>

<tr>
	<td>Password</td>
	<td>
		<input type="password" name="password" id="password" class="required"  maxlength="50">
	</td>
</tr>
<tr >
	<td colspan="2" >
		<a href="recuperarPassword.php">
			Olvide mi contrase&ntilde;a
		</a>
	</td>
</tr>

<tr>
	<td colspan="2" align="right">
		<input type="submit" name="enviar" value="Enviar" >
	</td>

</tr>
	
<tr>
	<td colspan="2" align="right" >
		<br/><a href="registro.php">Deseo registrarme</a>
	</td>
</tr>	
	<?php
	
	//Mostrar errores de validacion de usuario, en caso de que lleguen
	
		if( isset( $_POST['msg_error'] ) )
		{
			switch( $_POST['msg_error'] )
			{
				case 1:
			?>
			<script type="text/javascript"> 
				jAlert("El usuario o password son incorrectos.", "Seguridad");
				$("#password").focus();
			</script>
			<?php
				break;			
				case 2:
			?>
			<script type="text/javascript"> 
				jAlert("La seccion a la que intentaste entrar esta restringida.\n Solo permitida para usuarios registrados.", "Seguridad");
			</script>
			<?php		
				break;
			}		//Fin switch
		}

		//Mostrar mensajes del estado del registro
		
		if( isset( $_POST['status_registro'] ) )
		{
			switch( $_POST['status_registro'] )
			{
				case 1:
				if( $_POST['i_EmailEnviado'] ==1) {
				?>
					<script type="text/javascript"> 
						jAlert("Gracias, ha sido registrado exitosamente.\n Se le ha enviado un correo electronico de bienvenida, \npor favor, NO LO CONTESTE pues solo es informativo.", 'Registro');
					</script>
					<?php
				} else {
					?>
					<script type="text/javascript"> 
						jAlert("Gracias, ha sido registrado exitosamente.\n No se le ha podido enviar correo electronico de bienvenida, \nsin embargo, ya puede utilizar sus datos de acceso para iniciar sesion..", 'Registro');
					</script>
				<?php
				}

					break;			
				
				default:
			?>
				<script type="text/javascript"> 
					jAlert("Temporalmente NO se ha podido registrar, intente de nuevo mas tarde.", "Registro");
				</script>
			<?php		
			}		//Fin switch
		}
	?>
	
</table>
</form>
</body>
</html>

Como se puede ver para mostrar los mensajes de error utilizo la libreria JQuery, ya que me parecio que usar un alert() de javascript es algo feito, jajajaj. Como se ve el archivo en si solamente crea un formulario en el cual se dibujan dos cajas de texto; una para el usuario y otra para el password, un link para ir a la pantalla de recuperacion del password en caso de que al usuario se le haya olvidado y por ultimo se crea un boton tipo submit para enviar la informacion. Para validar campos vacios tambien utilizo JQuery. Ademas se puede ver que envio los dos datos de las cajitas a un archivo llamado validarUsuario.php por el metodo POST; el cual se encargara de accesar a la BD y verificar que los datos sean correctos.

Otra cosa interesante que se puede observar es que este archivo verifica si le llega un parametro llamado msg_error (con la funcion isset() de php) y en base a ese parametro (en realidad es un codigo de error) muestra un mensaje de error. A continuacion muestro un pantallazo como se ve el formulario en el navegador Chrome:

Pantalla de Login
En caso de que el usuario introduzca un nombre de usuario incorrecto se mostrara esta pantalla:
Pantalla Login, error usuario

Como se observa se ven mas atractivas las alertas con JQuery y ademas es sumamente facil utilizarlas.

validarUsuario.php

Este archivo es el que se encarga de recibir los datos del archivo index.php y los compara contra los que estan en la BD. Si el usuario y el password son correctos (existen en la BD) guarda el id del usuario en un formulario (el dato se envia oculto, hidden), inicializa una sesion , guarda algunas variables en dicha sesión y redirecciona hacia el archivo principal.php el cual es la pagina web que se supone debe mostrarse para usuarios registrados. En caso de que el usuario y/o password sean incorrectos entonces este archivo guarda igualmente un codigo de error en un formulario y redirecciona a la pagina de login, es decir, al archivo index.php. A continuacion se muestra su codigo fuente:
<?php
	/*
		Instituto Tecnologico de Zacatepec, Morelos 
	Descripcion:   Archivo que recibe los valores de 2 campos;
			un usuario y un password, los 2 datos se buscan si estan en la
			base de datos y redicciona al login o la pagina principal. 
	Author:     Gonzalo Silverio  gonzasilve@gmail.com 
	Archivo:    validarUsuario.php 
	*/ 

	//conectar BD
	include("conectar_bd.php");  
	conectar_bd();
	
	$usr = $_POST['usuario'];
	$pw = $_POST['password'];
	//Obtengo la version encriptada del password
	$pw_enc = md5($pw);
	
	$sql = "SELECT id_usuario FROM tbl_users
			INNER JOIN ctg_tiposusuario
			ON tbl_users.id_TipoUsuario = ctg_tiposusuario.id_TipoUsuario
			WHERE tx_username = '".$usr."'
			AND tx_password = '".$pw_enc."'	";	
	$result		=mysql_query($sql,$conexio); 

	$uid = "";
	
	//Si existe al menos una fila
	if( $fila=mysql_fetch_array($result) )
	{		
		//Obtener el Id del usuario en la BD 		
		$uid = $fila['id_usuario'];
		//Iniciar una sesion de PHP
		session_start();
		//Crear una variable para indicar que se ha autenticado
		$_SESSION['autenticado']    = 'SI';
		//Crear una variable para guardar el ID del usuario para tenerlo siempre disponible
		$_SESSION['uid']       		= $uid;
		//CODIGO DE SESION
		
		//Crear un formulario para redireccionar al usuario y enviar oculto su Id 
?>
		<form name="formulario" method="post" action="principal.php">
			<input type="hidden" name="idUsr" value='<?php echo $uid ?>' />
		</form>
<?php
	}
	else {
		//En caso de que no exista una fila...
		//..Crear un formulario para redireccionar al usuario a la pagina de login 
		//enviandole un codigo de error
?>
		<form name="formulario" method="post" action="index.php">
			<input type="hidden" name="msg_error" value="1">
		</form>
<?php
	}
?>
					
<script type="text/javascript"> 
	//Redireccionar con el formulario creado
	document.formulario.submit();
</script>
Como se observa; la mayoria del codigo esta comentado por lo que me ahorrare volver a explicar: Lo que si quiero mencionar es que en la linea 40 he dejado un comentario (CODIGO DE SESION), en esa linea si usted quiere puede generar un identificador de sesion, debido a que el ID de sesion de PHP a veces se pierde; usted puede crear un ID mas seguro; por ejemplo con base a la fecha y hr actual. la funcion session_id () permite leer o asignar el ID de la sesion.

La funcion session_start() permite iniciar una sesion o continuar una ya iniciada. Es por eso que en todas las paginas web que requieran que el usuario este autenticado se llama a esta funcion de PHP, esto lo podras ver en los demas archivos que mostrare mas adelante.

En la linea 37 y 39 se observa que es muy facil crear una variable de sesion con ayuda del array global $_SESSION[], basta con agregar un nuevo item y asignarle un valor, asi de facil. Posteriormente se pueden utilizar en cualquier pagina php por ejemplo para mostrar el Id del usuario y su Status en el navegador:
	echo "Id del usuario:".$_SESSION['uid'];
	echo "Ha iniciado sesion:".$_SESSION['autenticado'];

Facil ¿No?. Continuemos…

En la linea 12 del archivo validarUsuario.php se inserta un archivo llamado conectar_bd.php el cual se encarga de conectar con el DBMS, este archivo es el que muestro a continuacion…

conectar_bd.php

<?php
/*     
	Instituto Tecnologico de Zacatepec, Morelos 
Descripcion:   Conecta con el Manejador de Base de Datos (DBMS) y deja disponible una variable global (conexio)
		para ser utilizada posteriormente. 
Author:     Gonzalo Silverio  gonzasilve@gmail.com 
Archivo:    conectar_bd.php 
*/

$conexio;
function conectar_bd()
{
	global $conexio;
	//Definir datos de conexion con el servidor MySQL
	$elUsr = "root";
	$elPw  = "12345";
	$elServer ="localhost";
	$laBd = "prueba";
	
	//Conectar
	$conexio = mysql_connect($elServer, $elUsr , $elPw) or die (mysql_error());
	
	//Seleccionar la BD a utilizar
	mysql_select_db($laBd, $conexio ) or die (mysql_error());
}	
?>
Como se observa primero se definen los datos de conexion en variables locales a la funcion conectar_bd(). y posteriormente estas variables se usan como parametros para llamar a la funcion mysql_connect(), la cual es la que hace la peticion al dbms para conectarse. la funcion mysql_connect() devuelve un link que representa la conexion establecida al dbms, con este link guardado en la variable $conexio se selecciona la BD a utilizar (linea 24).

principal.php

Este archivo es la pantalla que el usuario ve si se logueo correctamente, nada mas como ejemplo he creado una muy sencilla. Cuando el usuario accede a esta pagina web se supone que ya paso por la pantalla de login y sus datos fueron verificados en la BD. Pero por seguridad antes de mostrarla verifico que efectivamente este logueado a travez de las variables de sesion que fueron creadas en el archivo validarUsuario.php. A continuacion muestro el codigo fuente:
<?php
/*     
	Instituto Tecnologico de Zacatepec, Morelos 
Descripcion:   Pantalla inicial que se muestra al usuario una vez que ha sido logueado correctamente. 
Author:     Gonzalo Silverio  gonzasilve@gmail.com 
Archivo:    principal.php 
*/

//Inicializar una sesion de PHP
session_start();

//Validar que el usuario este logueado y exista un UID
if ( ! ($_SESSION['autenticado'] == 'SI' && isset($_SESSION['uid'])) )
{
	//En caso de que el usuario no este autenticado, crear un formulario y redireccionar a la 
	//pantalla de login, enviando un codigo de error
?>
		<form name="formulario" method="post" action="index.php">
			<input type="hidden" name="msg_error" value="2">
		</form>
		<script type="text/javascript"> 
			document.formulario.submit();
		</script>
<?php
}

	//Conectar BD
	include("conectar_bd.php");  
	conectar_bd();

	//Sacar datos del usuario que ha iniciado sesion
	$sql = "SELECT  tx_nombre,tx_apellidoPaterno,tx_TipoUsuario,id_usuario
			FROM tbl_users
			LEFT JOIN ctg_tiposusuario
			ON tbl_users.id_TipoUsuario = ctg_tiposusuario.id_TipoUsuario
			WHERE id_usuario = '".$_SESSION['uid']."'";			
	$result		=mysql_query($sql); 

	$nombreUsuario = "";

	//Formar el nombre completo del usuario
	if( $fila = mysql_fetch_array($result) )
		$nombreUsuario = $fila['tx_nombre']." ".$fila['tx_apellidoPaterno'];
	
//Cerrrar conexion a la BD
mysql_close($conexio);
?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Inicio ::. Ejemplo autenticar usuarios</title>
	<link rel="stylesheet" href="estilos.css" type="text/css">
</head>
<body topmargin="0" >
<table align="right" width="350px" border="0">
<tr>												<!-- Dar Bienvenida al usuario -->
	<td  width="100px" align="right">Bienvenido <b><?php echo $nombreUsuario ?></b></td>
	<td  width="15px" align="center">
		<!-- Proporcionar Link para cerrar sesion -->
		<a href="cerrarSesion.php">Cerrar sesi&oacute;n</a>	
	</td>
</tr>
</table>
<br /><br />
<h2 align="center">Pantalla Principal</h2>

		<!-- Contenido inicial del sitio web -->
		
<body>
</html>
Como decia en la lineas anteriores, cuando una pagina esta restringida lo primero que se debe hacer es verificar que el usuario esta logueado y tiene permisos para ver dicha pagina. Como dije que no mostraria como dar permisos a los usuarios, en este ejemplo solo se comprueba que haya una sesion iniciada y que exista entre las variables de sesion un UID (User Id); Id del usuario en la Base de datos.

Si se verifica que esas condiciones se cumplen entonces se obtienen los datos del usuario, tal como su nombre , correo electronico, etc. Yo solo saque su nombre completo y lo mostre en la esquina superior derecha para que el usuario tenga la sensacion (jajajajj “sienta”) que a entrado al portal. A continuacion muestro un pantallazo de este archivo en el navegador:

Pantalla de inicio del usuario logueado

Como se observa tambien se ha puesto al usuario un link para que cierre su sesion.

Seguridad

Imaginemos que un usuario malintencionado escribe directamente la URL de este archivo en su navegador (escribe http://localhost/autenticar_usuarios/principal.php) pensando que con esto puede entrar y ver el contenido del sitio. Perdera su tiempo pues para eso presisamente se hace la validacion al inicio y solamente vera un mensaje de error como el que se ve a continuacion:

Mensaje de error al entrar a pagina principal sin login

cerrarSesion.php

Este archivo es al que apunta el enlace “Cerrar sesión ” que esta a un lado del nombre de usuario (una vez que ha iniciado su sesión). Este archivo se encarga de destruir todas las variables de sesión y terminar la sesion; todo esto se hace con las funciones que PHP ya trae incluidas.
<?php
/*     
	Instituto Tecnologico de Zacatepec, Morelos 
Descripcion:   Archivo para destruir las variables de sesion de un usuario logueado y terminar la sesion,
				 	ademas redirecciona nuevamente a la pagina de login. 
Author:     Gonzalo Silverio  gonzasilve@gmail.com 
Archivo:    cerrarSesion.php 
*/

session_start();
// Destruye todas las variables de la sesion
session_unset();
// Finalmente, destruye la sesion
session_destroy();

//Redireccionar a la pagina de login
header ("Location: index.php");

?>
Como se ve es muy corto el archivo. No doy mas explicacion ya que cada instruccion esta comentada.

recuperarPassword.php

En la pagina de login, si observas hay un link que dice Olvide mi contraseña, este link nos manda al archivo recuperarPassword.php. Este archivo permite enviar un nuevo password al usuario, el usuario solo debe escribir su correo electronico y automaticamente se generara un nuevo password de nueve caracteres y se le enviara a dicho email. Obviamente que el correo proporcionado se valida que exista en la BD; Como se observa en la BD el password esta encriptado en MD5 por lo que es necesario proporcionarle otro; no hay forma descifrar el password anterior.
<?php
	/*
		Instituto Tecnologico de Zacatepec, Morelos 
	Descripcion:   Este archivo permite preguntar al usuario su correo electronico para enviarle un nuevo
						password. 
	Author:     Gonzalo Silverio  gonzasilve@gmail.com 
	Archivo:    recuperarPassword.php 
	*/ 
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Recuperar Password ::. </title>
	
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	<link rel="stylesheet" href="estilos.css" type="text/css">
	<script src="jquery171.js" type="text/javascript"></script> 
	<script src="jquery.validate.js" type="text/javascript"></script>
	<script type="text/javascript" src="jquery.alerts.js"></script>
	<link href="jquery.alerts.css" rel="stylesheet" type="text/css" />
	
	<script type="text/javascript">
	<!--
		$().ready(function() {
		$("#recPassword").validate({
		rules: {
		/*A continuacion los nombres de los campos y sus reglas a cumplir */
			correo2: {
			required: true,
			email: true,
			equalTo: "#correo"
			},
			correo: {
			required: true,
			email: true
			}


		}
		});
		$("#correo").focus();
		});
	// -->
	</script>
	
</head>
<body>
<br /><br />


<form id="recPassword" name="recPassword"  method="POST" action="recuperarPassword.php">

<table align="center" width="400px">

<tr>
	<td colspan="2" align="center"><h3><b>Recuperar Password</b></h3></td>
</tr>

<?php
//Si llega el parametro correo y no viene vacio
if( isset( $_POST['correo'] ) && $_POST['correo'] != '' )
{
	//Conectar la BD
	include("conectar_bd.php");  
	conectar_bd();

	//Recuperar la direccion de email que llega
	$elcorreo   = $_POST['correo'];
	
	//Verificar si existe el correo en la BD
	$sql = "SELECT  id_usuario,tx_username,tx_nombre,tx_apellidoPaterno
			FROM tbl_users
			WHERE tx_correo = '".$elcorreo."'";			
	$rs_sql	= mysql_query($sql);

	//Si no existe el correo... 
	if ( !( $fila 	= mysql_fetch_object($rs_sql) )  )
	{
	//Mostrar msg de error al usuario (en esta misma pagina)
?>
	<input type="hidden" id="error" value="1">			
	<script type="text/javascript"> 
	location.href="recuperarPassword.php?error="+document.getElementById('error').value;
	</script>
<?php
	}
	
	//En caso de que si exista un email como el k llega, leer de la BD los datos del usuario
	$idusr 	= $fila->id_usuario;		//Servira para actualizar el pw
	$nombre = $fila->tx_nombre." ".$fila->tx_apellidoPaterno;
	$nick 	= $fila->tx_username;
	
	// Generacion de un nuevo Password
	$pasw = "";
	$abecedario = array("A","B","C","D","E","F","G","H","J","K","L","M","N","O","P","Q","R","S","T",
"U","V","W","a","b","c","d","e","f","g","h","j","k","l","m","n","o","p","q","r","s","t","u","v","w");
	$simbolos 	= array(",","}","{","-","|","!","#","$","%","&","/","(",")","=","?","¡",
"*","]","[","_",":",";","+");
	for($i=0;$i<3; $i++)
	{
		$md 	= rand(1,2);
		$pasw 	.=  (($md%2)==0) ? $abecedario[rand(0,43)] : rand(0,9);  
		$md 	= rand(1,2);
		$pasw 	.=  (($md%2)==0) ? rand(0,9) :  $simbolos[rand(0,23)];  
		$md 	= rand(1,2);
		$pasw 	.=  (($md%2)==0) ?   $simbolos[rand(0,23)] : $abecedario[rand(0,43)] ;		
	}		
	
	// Le  Envio  por correo electronico  su nuevo password 
     $seEnvio;			//Para determinar si se envio o no el correo
     $destinatario = $elcorreo;				//A quien se envia
     $nomAdmin 			= 'Gonzalo Silverio';		//Quien envia
	 $mailAdmin 		= 'gonzasilve@gmail.com';	//Mail de quien envia
	 $urlAccessLogin = 'http://localhost/autenticar_usuarios/';	//Url de la pantalla de login

     $elmensaje = "";     
     $asunto = "Nueva contraseña para ".$nick;

     $cuerpomsg ='
		<h3>.::Recuperar Password::.</h3>
		<p>A peticion de usted; se le ha asignado un nuevo password, utilice los siguientes datos para acceder al sistema</p>
		  <table border="0" >
			<tr>
			  <td colspan="2" align="center" ><br> Nuevos datos de acceso para <a href="'.$urlAccessLogin.'">'.$urlAccessLogin.'</a><br></td>
			</tr>
			<tr>
			  <td> Nombre </td>
			  <td> '.$nombre.' </td>
			</tr>
			<tr>
			  <td> Username </td>
			  <td> '.$nick.' </td>
			</tr>
			<tr>
			  <td> Password </td>
			  <td> '.$pasw.' </td>
			</tr>
		  </table> ';
		  
	date_default_timezone_set('America/Mexico_City');
		  
	//Establecer cabeceras para la funcion mail()
	//version MIME
	$cabeceras = "MIME-Version: 1.0\r\n";
	//Tipo de info
	$cabeceras .= "Content-type: text/html; charset=iso-8859-1\r\n";
	//direccion del remitente
	$cabeceras .= "From: ".$nomAdmin." <".$mailAdmin.">";
	$resEnvio = 0;
	//Si se envio el email
	if(mail($destinatario,$asunto,$cuerpomsg,$cabeceras))
	{
		//Actualizar el pwd en la BD
		$sql_updt = "UPDATE tbl_users SET tx_password = '".md5($pasw)."' 
		WHERE (id_usuario = ".$idusr.")
		AND (tx_correo = '".$elcorreo."')";
		$res_updt = mysql_query($sql_updt);
		$resEnvio = 1;
	}

	//Cerrrar conexion a la BD
	mysql_close($conexio);
		
	// Mostrar resultado de envio (en esta misma pagina)
	?>
		<input type="hidden" id="enviado" value="<?php echo $resEnvio ?>">
		<input type="hidden" id="elcorreo" value="<?php echo $elcorreo ?>">
		<script type="text/javascript">
			location.href="recuperarPassword.php?enviado="+document.getElementById('enviado').value+"&elcorreo="+document.getElementById('elcorreo').value;
		</script>
	<?php	
}
else
{
?>

<tr>
	<td colspan="2">Escriba su correo electronico con el que se ha registrado, 
		se le enviara un nuevo password a su correo electronico:<br /><br /> 
	</td>
</tr>

<tr>
	<td>Correo electronico:</td>
	<td>
		<input type="text" name="correo" id="correo"  maxlength="50" />
	</td>
</tr>
<tr>
	<td>Confirme Correo electronico:</td>
	<td>
		<input type="text" name="correo2" id="correo2" maxlength="50" />
	</td>
</tr>

<?php
	//Si llega un codigo de error
	if( isset($_GET['error']) && $_GET['error']==1 )
	{
		echo "<tr><td colspan='2'><br><font color='red'>El correo electronico no pertenece a ningun usuario registrado.</font><br></td></tr>";
	}
	else if( isset($_GET['enviado']) && isset($_GET['elcorreo'])  )
	{
		//Si se envio correctamente el nuevo password
		if( $_GET['enviado']==1 ) 
			echo "<tr><td colspan='2'><br><font color='green'>Su nueva contrase&ntilde;a ha sido enviada a <strong>".$_GET['elcorreo']."</strong>.</font><br></td></tr>";
		else if( $_GET['enviado']==0 ) 
			echo "<tr><td colspan='2'><br><font color='red'>Por el momento la nueva contrase&ntilde;a no pudo ser enviada a <strong>".$_GET['elcorreo']."</strong>.<br>
			Intente de nuevo mas tarde.</font></td></tr>";
	}
?>

<tr>
	<td align="center" colspan="2">
		<br /><br /> 
		<input type="button" onClick="javascript: location.href='index.php'" name="cancelar" value="Cancelar" >
		&nbsp;&nbsp;&nbsp;&nbsp;
		<input type="submit" name="enviar" value="Enviar" >
	</td>
</tr>

<?php
}
?>

</table>
</form>
</body>
</html>

Para mas seguridad el password nunca se muestra al usuario, por el contrario; se le asigna otro (formado aleatoriamente) y se le envia por correo electronico. Como se observa en la linea 60 se comienza comprobando si llega un parametro llamado ‘correo’; si llega esto quiere decir que el formulario de recuperacion de password ya fue enviado y el correo que esta llegando es de un usuario al que se le debe asignar un nuevo password. Por el contrario; sino llega, se dibujan dos cajas de texto para permitir al usuario escribir su correo electronico y se le pueda enviar su password.

Bueno, supongamos que a este archivo le llega un el parametro correo, entonces de la linea 62 a la linea 85 se comprueba si ese email existe en la BD. sino existe, entonces se redirecciona al usuario a este mismo archivo pero con un codigo de error, el cual servira para mostrar un texto al usuario avisando que su correo electronico no existe. En caso de que si exista el email en la BD (no se cumple la condicion de la linea 76) entonces se recuperan los datos del usuario (linea 88 a la 90) y posteriormente se le genera un nuevo password (linea 93 a la 104), observe la forma como he generado el nuevo password del usuario; cada ciclo agrega 3 caracteres: el primero puede ser una letra ho un numero, el segundo puede ser un numero o un simbolo del array con el mismo nombre, el tercero puede ser un simbolo o una letra (Como son tres ciclos entonces el password tendra nueve caracteres).

Y ya por ultimo se le envia el password a su correo electronico del usuario (linea 106 a la linea 165). Algo que me gustaria resaltar es que el nuevo password debe ser actualizado en la BD para que la proxima vez el usuario intente iniciar sesion pues este password sea valido, ademas, solo se debe de actualizar despues de notificar al usuario (envio de email correcto), tal como se hace en este ejemplo.

A continuacion pongo una imagen del error que aparece en caso de que el email escrito no exista:

El email no existe en la Base de datos

Mensaje en caso de que el email haya sido enviado correctamente:

Nuevo password asignado correctamente

Ya no pongo el mensaje del error en caso de que NO se envie el email (falle la funcion mail() de php), porque es muy obvia, pero, a continuación dejo una imagen del eMail que le llega al usuario, con sus nuevos datos de acceso:

Email con nuevo password del usuario

registro.php

A peticion de muchos de los visitantes que preguntan (ya sea en privado o en comentarios de esta entrada) como registrar usuarios en php decidi exponer un ejemplo. En la pantalla de Login si observas aparece un enlace (hipervinculo) con la leyenda Deseo registrarme; el codigo que muestro a continuacion es del archivo que se muestra en el navegador al dar click en dicho enlace. Este archivo, en resumen, muestra un formulario creado con HTML para que el usuario capture sus datos personales y datos de acceso (username y password) envie dichos datos al script guardarRegistro.php que guarda los datos en la base de datos. El codigo es este…
<?php
	/*
		Instituto Tecnologico de Zacatepec, Morelos
	Descripcion:   Este archivo muestra un formulario que permite al usuario
		capturar sus datos y personales y de acceso.
	Author:     Gonzalo Silverio  gonzasilve@gmail.com
	Archivo:    registro.php
	*/

$str_nombre 		= "";
$str_apPaterno 	= "";
$str_apMaterno 	= "";
$str_correo 		= "";
$str_username 	= "";
$str_password 	= "";
$str_password2 	= "";

if( isset($_POST['str_nombre']) ) 		
	$str_nombre 		= trim($_POST['str_nombre']);
if( isset($_POST['str_apPaterno']) ) 
	$str_apPaterno 	= trim($_POST['str_apPaterno']);
if( isset($_POST['str_apMaterno']) ) 
	$str_apMaterno 		= trim($_POST['str_apMaterno']);
if( isset($_POST['str_correo']) ) 
	$str_correo 	= trim($_POST['str_correo']);
if( isset($_POST['str_username']) ) 
	$str_username 	= trim($_POST['str_username']);
if( isset($_POST['str_password']) ) 
	$str_password 	= trim($_POST['str_password']);
if( isset($_POST['str_password2']) ) 
	$str_password2 	= trim($_POST['str_password2']);


?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Registrar Usuario ::. </title>

	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	<link rel="stylesheet" href="estilos.css" type="text/css">
	<script src="jquery171.js" type="text/javascript"></script>
	<script src="jquery.validate.js" type="text/javascript"></script>
	<script type="text/javascript" src="jquery.alerts.js"></script>
	<link href="jquery.alerts.css" rel="stylesheet" type="text/css" />

	<script type="text/javascript">
	<!--
		$().ready(function() {
		$("#registrar_usuario").validate({
		rules: {
		/*A continuacion los nombres de los campos y sus reglas a cumplir */
			tx_nombre: {
				required: true,	minlength: 3
			},
			tx_apPaterno: {
				required: true, minlength: 3
			},
			tx_apMaterno: {
				required: true,	minlength: 3
			},
			tx_correo: {
				required: true,	minlength: 5, email: true
			},
			tx_username: {
				required: true,	minlength: 5
			},
			tx_password: {
				required: true,	minlength: 5
			},
			tx_password2: {
				required: true,	minlength: 5,	equalTo: "#tx_password"
			}

		},
		/*A continuacion los campos y los mensajes en caso de que no se cumplan las reglas */
		messages: {
			tx_nombre: {
				required: "Por favor, escriba su Nombre.",
				minlength: jQuery.format("Su Nombre como minimo debe tener {0} caracteres.")
			},
			tx_apPaterno: {
				required: "Por favor, escriba su Apellido Paterno.",
				minlength: jQuery.format("Su Apellido Paterno como minimo debe tener {0} caracteres.")
			},
			tx_apMaterno: {
				required: "Por favor, escriba su Apellido Materno.",
				minlength: jQuery.format("Su Apellido Materno como minimo debe tener {0} caracteres.")
			},
			tx_correo: {
				required: "Por favor, escriba una direccion de correo electronico valida.",
				minlength: jQuery.format("Por favor, escriba una direccion de correo electronico valida.")
			},
			tx_username: {
				required: "Por favor, escriba un nombre de usuario. Este dato le servira para iniciar sesion y ver el contenido.",
				minlength: jQuery.format("Su nombre de usuario como minimo debe tener {0} caracteres.")
			},
			tx_password: {
				required: "Por favor, escriba una contraseña.",
				minlength: jQuery.format("Su contraseña como minimo debe tener {0} caracteres.")
			},
			tx_password2: {
				required: "Por favor, repita la contraseña anterior.",
				minlength: jQuery.format("Su contraseña como minimo debe tener {0} caracteres."),
				equalTo: "Por favor, repita la contraseña anterior.",
			}

		}

		});
		$("#tx_nombre").focus();
		});
	// -->
	</script>

</head>
<body>
<br />


<form id="registrar_usuario" name="registrar_usuario"  method="POST" action="guardarRegistro.php">

<table align="center" width="600px">

<tr>
	<td colspan="2" align="center"><h3><b>Registrar usuario</b></h3></td>
</tr>

<tr>
	<td colspan="2">Gracias por tu interes en registrarte. Para hacerlo, solo debes llenar
	los siguientes campos y pulsar el boton <b>Registrarme</b>. Para hacer mas rapido el registro y
	asi tu puedas acceder al contenido, tu cuenta se activa inmediatamente.<br /><br />
	</td>
</tr>
	
	<?php
		//Si llega el parametro error y no viene vacio
		if( isset( $_POST['error'] ) && $_POST['error'] != '' ) {
	?>
		<tr>
			<td colspan="2" >
				<font color="red">
				<ul>
					<?php
						echo $_POST['msgs_error'];
					?>
				</ul>
				</font>
			</td>
		</tr>
	<?php
		}
	?>

	
	<tr>
		<td><label for="tx_nombre">Nombre(s)</label></td>
		<td>
			<input type="text" name="tx_nombre" id="tx_nombre" value='<?php echo $str_nombre ?>' size="30"  maxlength="30" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_apPaterno">Apellido paterno</label></td>
		<td>
			<input type="text" name="tx_apPaterno" id="tx_apPaterno" value='<?php echo $str_apPaterno ?>' size="30"  maxlength="30" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_apMaterno">Apellido materno</label></td>
		<td>
			<input type="text" name="tx_apMaterno" id="tx_apMaterno"  value='<?php echo $str_apMaterno ?>' size="30"  maxlength="30" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_correo">Correo electronico</label></td>
		<td>
			<input type="text" name="tx_correo" id="tx_correo"  value='<?php echo $str_correo ?>' size="30"  maxlength="30" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_username">Nombre de usuario</label></td>
		<td>
			<input type="text" name="tx_username" id="tx_username"  value='<?php echo $str_username ?>' size="25"  maxlength="25"  />
		</td>
	</tr>
	<tr>
		<td><label for="tx_password">Contrase&ntilde;a</label></td>
		<td>
			<input type="password" name="tx_password" id="tx_password"  value='<?php echo $str_password ?>'  size="25"  maxlength="25" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_password2">Confirme la contrase&ntilde;a</label></td>
		<td>
			<input type="password" name="tx_password2" id="tx_password2"  value='<?php echo $str_password2 ?>'  size="25"  maxlength="25" />
		</td>
	</tr>
	<tr>
		<td>Tipo de usuario</td>
		<td>
			<input type="hidden" name="i_tipoUsuario" id="i_tipoUsuario" value="2"   />
			<input type="radio" name="rad_TipoUsuario" id="rad_TipoUsuario" disabled value="2" checked="checked"  /> Usuario normal &nbsp;&nbsp;&nbsp;
			<input type="radio" name="rad_TipoUsuario" id="rad_TipoUsuario" disabled value="1"  /> Administrador
		</td>
	</tr>

<tr>

	<td align="center" colspan="2">
		<br /><br />
		<input type="button" onClick="javascript: location.href='index.php'" name="cancelar" value="Cancelar" >
		&nbsp;&nbsp;&nbsp;&nbsp;
		<input type="submit" name="registrarme" value="Registrarme" >
	</td>
</tr>

</table>
</form>
</body>
</html>
Como puedes observar esta un poco extenso (como 200 lineas sin lineas en blanco); ese es el precio de validar de una manera rigurosa los datos que el usuario introduce en los cuadros de texto. Tratare de explicar un poco este archivo, pero antes te muestro una imagen de la pagina web que se genera a partir del codigo fuente anterior:

Pagina web para registrar usuarios

De la linea 10 a 16 se declaran y limpian variables, una para cada dato del usuario que se va a registrar, enseguida en la linea 18 se verifica si esta llegando (si exite, con isset()) la variable de str_nombre, si se cumple que si existe dicha variable; hay una variable con el mismo nombre que se declaro antes (linea 10), entonces se le asigna el valor que llega. Cuando llegan datos significa que ya se habian enviado los datos al archivo guardarRegistro.php y éste los esta regresando si no los pudo guardar. Esta operacion la realiza para cada dato del usuario.

Si continuamos viendo el codigo se observa que de la linea 50 a la 100 es codigo javascript donde ajustamos parametros del plugin de validacion de JQuery. A este tipo de validacion se le conoce como validacion del lado cliente, en este caso el cliente es el navegador.

En la linea 121 se observa que esta escrito el encabezado del formulario y en su parametro action estamos diciendole que envie los datos de dicho formulario al archivo guardarRegistro.php el cual se encargara de guardarlos en la base de datos (no sin antes validarlos en el lado servidor).

En la linea 138 estamos verificando si existe/llega una variable llamada error y en caso de que si, mostramos la lista de errores que ocurrieron al guardar. La lista de errores vienen en otra variables llamada msg_error. Observa como en la linea 143 y 147 se abre y cierra, respectivamente una lista desordenada de HTML, la variable msg_error trae los <li> </li> correspondientes, cada <li> es un error que ocurrio al intentar guardar en el archivo guardarRegistro.php. En caso de que hayan ocurrido errores se mostrara una pantalla similar a esta:

Horrores al registrar un usuario

guardarRegistro.php

Este archivo recibe los datos del archivo registro.php y los guarda en la base de datos. Antes de guardar realiza varias validaciones, mas abajo esta la explicacion pero, veamos el codigo…
<?php
	/*
		Instituto Tecnologico de Zacatepec, Morelos
	Descripcion:   Este archivo permite guardar un nuevo usuario.
	Author:     Gonzalo Silverio  gonzasilve@gmail.com
	Archivo:    guardarRegistro.php
	*/
	//Recuperar los datos del formulario de registro
	$str_nombre			=trim($_POST['tx_nombre']);
	$str_apPaterno	=trim($_POST['tx_apPaterno']);
	$str_apMaterno	=trim($_POST['tx_apMaterno']);
	$str_correo			=trim($_POST['tx_correo']);
	$str_username		=trim($_POST['tx_username']);
	$str_password		=trim($_POST['tx_password']);
	$str_password2	=trim($_POST['tx_password2']);
	$i_TipoUsuario	=trim($_POST['i_tipoUsuario']);

	//Devuelve true si la cadena que llega esta VACIA
	function estaEnBlanco($cadena) {
		if(strlen( trim($cadena) ) == 0 )
			return true;
		return false;
	}

	//Devuelve true si la longitud de la cadena (primer parametro)
	// que llega  es menor que el numero (segundo parametro)
	function validaTamanio($cadena,$longitud) {
		if(strlen( trim($cadena) ) < $longitud )
			return true;
		return false;
	}

	// devuelve true SI ha escrito, un email NO VALIDO
	function esCorreoInvalido($str_email) {
		if(!filter_var(trim($str_email), FILTER_SANITIZE_EMAIL))
			return true;
		return false;
	}

	// devuelve una cadena escapada de algunos caracteres que
	// pudieran servir para un ataque de sql injection
	function escaparQuery($cadena) {
		$str_KeywordsSQL 			= array("select ","insert ","delete ","update ","union ");
		$str_OperadoresSQL 		= array("like ","and ","or ","not ","<",">","<>","=","<");
		$str_DelimitadoresSQL = array(";","(",")","'");

		//Quitar palabras reservadas y operadores
		for($i=0; $i<count($str_KeywordsSQL); $i++) {
			$cadena = str_replace($str_KeywordsSQL[$i], "",strtolower($cadena) );
		}
		for($i=0; $i<count($str_OperadoresSQL); $i++) {
			$cadena = str_replace($str_OperadoresSQL[$i], "",strtolower($cadena) );
		}
		for($i=0; $i<count($str_DelimitadoresSQL); $i++) {
			$cadena = str_replace($str_DelimitadoresSQL[$i], "",strtolower($cadena) );
		}

		return $cadena;
	}


	$mensajesAll= "";

	//Mensajes para el nombre
	if( estaEnBlanco($str_nombre) )
		$mensajesAll = "<li>Por favor, escriba su Nombre.</li>";
	if( validaTamanio($str_nombre,3) )
		$mensajesAll .= "<li>Su Nombre como minimo debe tener 3 caracteres.</li>";
	//Mensajes para el Apellido Paterno
	if( estaEnBlanco($str_apPaterno) )
		$mensajesAll .= "<li>Por favor, escriba su Apellido Paterno.</li>";
	if( validaTamanio($str_apPaterno,3) )
		$mensajesAll .= "<li>Su Apellido Paterno como minimo debe tener 3 caracteres.</li>";
	//Mensajes para el Apellido Materno
	if( estaEnBlanco($str_apMaterno) )
		$mensajesAll .= "<li>Por favor, escriba su Apellido Materno.</li>";
	if( validaTamanio($str_apMaterno,3) )
		$mensajesAll .= "<li>Su Apellido Materno como minimo debe tener 3 caracteres.</li>";
	//Mensajes para el Correo electronico
	if( estaEnBlanco($str_correo) || validaTamanio($str_correo,5) || esCorreoInvalido($str_correo) )
		$mensajesAll .= "<li>Por favor, escriba una direccion de correo electronico valida.</li>";
	//Mensajes para el nombre de usuario
	if( estaEnBlanco($str_username) )
		$mensajesAll .= "<li>Por favor, escriba un nombre de usuario. Este dato le servira para iniciar sesion y ver el contenido.</li>";
	if( validaTamanio($str_username,5) )
		$mensajesAll .= "<li>Su nombre de usuario como minimo debe tener 5 caracteres.</li>";
	//Mensajes para el password
	if( estaEnBlanco($str_password) )
		$mensajesAll .= "<li>Por favor, escriba una contrase&ntilde;a.</li>";
	if( validaTamanio($str_password,5) )
		$mensajesAll .= "<li>Su contrase&ntilde;a como minimo debe tener 5 caracteres.</li>";
	//Mensajes para la confirmacion del password
	if( estaEnBlanco($str_password2) || validaTamanio($str_password2,5) )
		$mensajesAll .= "<li>Por favor, confirme la contrase&ntilde;a anterior.</li>";
	if( trim($str_password) != trim($str_password2) )
		$mensajesAll .= "<li>Por favor, repita la contrase&ntilde;a anterior.</li>";	
	//Mensajes para el tipo de usuario
	if( estaEnBlanco($i_TipoUsuario) )
		$mensajesAll .= "<li>Por favor, indique el tipo de usuaurio.</li>";

	$log = $mensajesAll."<br>";

	//Si se generaron mensajes de error al validar...
	if ( trim($mensajesAll) != "" )	{
		//..Redireccion a la pagina de registro para mostrar msg de error al usuario
		//Enviar los datos que habia escrito antes de enviar
	?>
	<form id="frm_error"   name="frm_error" method="post" action="registro.php">
		<input type="hidden" name="error" value="1" />
		<input type="hidden" name="msgs_error" value='<?php echo $mensajesAll ?>' />
		<input type="hidden" name="str_nombre" value='<?php echo $str_nombre ?>' />
		<input type="hidden" name="str_apPaterno" value='<?php echo $str_apPaterno ?>' />
		<input type="hidden" name="str_apMaterno" value='<?php echo $str_apMaterno ?>' />
		<input type="hidden" name="str_correo" value='<?php echo $str_correo ?>' />
		<input type="hidden" name="str_username" value='<?php echo $str_username ?>' />
		<input type="hidden" name="str_password" value='<?php echo $str_password ?>' />
		<input type="hidden" name="str_password2" value='<?php echo $str_password2 ?>' />
	</form>
	<script type="text/javascript">
		//Redireccionar con el formulario creado
		document.frm_error.submit();
	</script>
<?php
		exit;
	}
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Registrar Usuario ::. </title>

	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<link rel="stylesheet" href="estilos.css" type="text/css">
	<script src="jquery171.js" type="text/javascript"></script>
	<script src="jquery.validate.js" type="text/javascript"></script>
	<script type="text/javascript" src="jquery.alerts.js"></script>
	<link href="jquery.alerts.css" rel="stylesheet" type="text/css" />

	<script type="text/javascript">
	<!--
		$().ready(function() {

		});
	// -->
	</script>

</head>
<body>

<?php
	$mensajesAll				= "";
	$username_duplicado = false;
	$email_duplicado 		= false;
	//Escapar las cadenas para avitar SQL Injection
	$str_username = escaparQuery($str_username);
	$str_correo 	= escaparQuery($str_correo);

	//Conectar la BD
	include("conectar_bd.php");
	conectar_bd();

	
	//Validar que el nombre de usuario no exista en la BD
	$sql = "SELECT  id_usuario	FROM tbl_users
	WHERE tx_username = '".trim($str_username)."';";
	$rs_sql	= mysql_query($sql);
	$log .=  $sql."<br>";
		
	//Si ya existe el usuario en la BD...
	if ( $fila 	= mysql_fetch_object($rs_sql) )	{
		$mensajesAll = "<li>El nombre de usuario <b>".$str_username."</b> ya fue registrado 
		por otra persona. Por favor, escriba otro.</li>";
		$username_duplicado = true;
	}

	//Validar que el email no exista en la BD
	$sql = "SELECT  id_usuario	FROM tbl_users
	WHERE tx_correo='".$str_correo."';";
	$rs_sql	= mysql_query($sql);
	$log .=  $sql."<br>";

	
	//Si ya existe el email en la BD...
	if ( $fila 	= mysql_fetch_object($rs_sql) )	{
		$mensajesAll = "<li>El correo electronico <b>".$str_correo."</b> ya fue registrado 
		por otra persona. Por favor, escriba otro.</li>";
		$email_duplicado 		= true;
	}
	//Si ambos datos ya estan en la Base de datos mostrar un solo msg
	if( $username_duplicado && $email_duplicado)
		$mensajesAll = "<li>Ambos, nombre de usuario <b>".$str_username."</b> 
		y correo electronico <b>".$str_correo."</b> ya fueron registrados por otra persona.
		Por favor, cambie esos datos.</li>";
	//..Redireccion a la pagina de registro para mostrar msg de error al usuario
	//Enviar los datos que habia escrito antes de enviar
	
	$log .=  $mensajesAll."<br>";

	
	if ( trim($mensajesAll) != "" )	{
		//..Redireccion a la pagina de registro para mostrar msg de error al usuario
		//Enviar los datos que habia escrito antes de enviar
		?>
		<form id="frm_error"   name="frm_error" method="post" action="registro.php">
			<input type="hidden" name="error" value="2" />
			<input type="hidden" name="msgs_error" value='<?php echo $mensajesAll ?>' />
			<input type="hidden" name="str_nombre" value='<?php echo $str_nombre ?>' />
			<input type="hidden" name="str_apPaterno" value='<?php echo $str_apPaterno ?>' />
			<input type="hidden" name="str_apMaterno" value='<?php echo $str_apMaterno ?>' />
			<input type="hidden" name="str_correo" value='<?php echo $str_correo ?>' />
			<input type="hidden" name="str_username" value='<?php echo $str_username ?>' />
			<input type="hidden" name="str_password" value='<?php echo $str_password ?>' />
			<input type="hidden" name="str_password2" value='<?php echo $str_password2 ?>' />
		</form>
		<script type="text/javascript">
			//Redireccionar con el formulario creado
			document.frm_error.submit();
		</script>
			<?php
		exit;
	}
	
	
	//..Si llega asta aqui es que todos los datos son validos, procedemos a darlo de alta en BD
	$str_elNombre 				= $str_nombre." ".$str_apPaterno;
	$str_elNombreCompleto = $str_nombre." ".$str_apPaterno." ".$str_apMaterno;

	
	//Formar el query para el insert del nuevo usuario
	$queryInsert="INSERT INTO tbl_users (
	tx_nombre,
	tx_apellidoPaterno,
	tx_apellidoMaterno,
	tx_correo,
	tx_username,
	tx_password,
	id_TipoUsuario,
	dt_registro	) 
	VALUES(
	'".$str_nombre."',
	'".$str_apPaterno."',
	'".$str_apMaterno."',
	'".$str_correo."',
	'".$str_username."',
	'".md5($str_password)."',
	".$i_TipoUsuario.",
'".date("Y-m-d H:i:s")."');";
	
	$log .=  $queryInsert."<br>";

	//echo $log;
	//exit;
	
	mysql_query($queryInsert);

	// Le  Envio  un correo electronico  de bienvenida
	$destinatario = $str_correo;					//A quien se envia
	$nomAdmin 			= 'Gonzalo Silverio';			//Quien envia
	$mailAdmin 		= 'gonzasilve@gmail.com';		//Mail de quien envia
	$urlAccessLogin = 'http://localhost/autenticar_usuarios';		//Url de la pantalla de login

	$elmensaje = "";
	$asunto = $str_elNombre.", Gracias por registrarte!";

	$cuerpomsg ='
	<h2>.::Registrar usuarios::.</h2>
	<p>Le damos la mas cordial bienvenida, desde ahora usted podra gozar de los beneficios de 
	haberse identificado y acceder a contenido exclusivo de esta comunidad.</p>
		<table border="0" >
		<tr>
			<td colspan="2" align="center" >Sus datos de acceso para <a href="'.$urlAccessLogin.'">'.$urlAccessLogin.'</a><br></td>
		</tr>
		<tr>
			<td> Nombre </td>
			<td> <b>'.$str_elNombreCompleto.'</b> </td>
		</tr>
		<tr>
			<td> Nombre de usuario </td>
			<td> <b>'.$str_username.'</b> </td>
		</tr>
		<tr>
			<td> Password </td>
			<td> <b>'.$str_password.'</b> </td>
		</tr>
		</table> <br/><br/>
	<p><b>Gracias por su preferencia, hasta pronto.</b></p> <br><br>';

	date_default_timezone_set('America/Mexico_City');

	//Establecer cabeceras para la funcion mail()
	//version MIME
	$cabeceras = "MIME-Version: 1.0\r\n";
	//Tipo de info
	$cabeceras .= "Content-type: text/html; charset=iso-8859-1\r\n";
	//direccion del remitente
	$cabeceras .= "From: ".$nomAdmin." <".$mailAdmin.">";
	$i_EmailEnviado = 0;
	
	//Si se envio el email
	if( mail($destinatario,$asunto,$cuerpomsg,$cabeceras) )	
		$i_EmailEnviado = 1;
	
	//Cerrrar conexion a la BD
	mysql_close($conexio);

	// Mostrar resultado del registro
	?>
	<form id="frm_registro_status"   name="frm_registro_status" method="post" action="index.php">
		<input type="hidden" name="status_registro" value="1" />
		<input type="hidden" name="i_EmailEnviado" value='<?php echo $i_EmailEnviado ?>' />
	</form>
	<script type="text/javascript">
		//Redireccionar con el formulario creado
		document.frm_registro_status.submit();
	</script>
</body>
</html>

Empezamos recogiendo en varibles locales a este archivo los datos que nos llegan del archivo registro.php, esto se hace de la linea 8 a l6. Despues definimos 4 funciones, las cuales mas adelante nos serviran para hacer validaciones con los datos que acabamos de recibir. Cada una tiene un breve explicación asi que me ahorrare volver a hacerlo.

De la linea 64 a 99 validamos que los datos que llegan no vengan vacios (en blanco), ademas para algunos campos como el username y password validamos su tamaño. Observa como para cada campo que pudiera venir vacio o no cumplir el tamaño se siguen revisando los demas pero se agrega un item <li> con la descripcion del error. En la linea 104 se revisa si la lista NO esta vacia, sino esta vacia entonces regresamos todos los datos al archivo registro.php, para que el usuario no tenga que volver a escribirlos y solo corrija los que tienen error, y ademas mandamos una variable llamada error y la lista de errores que ocurrieron (con su descripcion). Ademas de mandar los errores debemos detener la ejecucion de este archivo, esto se hace en la linea 124.

Supongamos que no hubo errores de campos en blanco ni tamaños, entonces no se cumplira la condicion de la linea 104, entonces, el interprete de PHP se saltara hasta la linea 126 y continuara su ejecucion…

Lo que haremos ahora sera validar que el nombre de usuario e email escrito no existan en la BD, si algunos de los dos ya fue registrado volveremos a direccionar la ejecucion al archivo registro.php para que escriba otro username/pasword. Esto se hace de la linea 151 a 231, el codigo esta comentado por lo tanto evitare redundar en la explicacion.

Tal y como dice la linea 224, si la ejecucion llega asta dicha linea es que todos los datos son validos (han pasado las validaciones), entonces procedemos a darlo de alta en la base de datos. Despues de formar la sentencia SQL (insert) de la linea 230 a 247, se ejecuta (linea 254) y con lo cual el usuario ha sido dado de alta. Observa como en varios puntos del script voi guardando un log de la ejecucion (errores, querys, etc) en una variable llamada $log puedes imprimirla y detener la ejecucion en cualquier momento para ver que pasa detras del telon, observa como lo hago yo en la linea 251 y 252.

Como un plus e puesto el codigo como se le pueden enviar sus datos de acceso en un email, si recuerdas ya vimos como enviar un email en PHP en otra entrada de blog. A continuación un pantallazo del email que le llega al usuario que se acaba de registrar:
Email con sus datos de acceso
 
 
Despues de enviarle el email con sus datos direccionamos al usuario al archivo index.php (recuerda que ahi dio click en el enlace Deseo registrarme) junto con una bandera; $status_registro si esta bandera llega con valor 1 significa que el registro fue exitoso. el archivo index.php ya esta preparado para revisar si le llega esta bandera (fijate en linea 99). Pantalla de aviso que ha sido registrado:

Aviso de registro exitoso

Por ultimo no hay que olvidarse de cerrar la conexion a la base de datos, esto lo hago en la linea 304 del archivo guardarRegistro.php.

Demo

Si deseas ver el ejemplo funcionando Da click aqui. usa estos datos para probar el ejemplo, Usuario: visitante_wp, Contraseña: 12345. Si te registras no olvides revisar el SPAM!.
 
 
Bueno, eso es todo. Como siempre, si quieres el codigo deja tu email y te lo envio a la brevedad.  Si te gusto el articulo ¿me regalas un like?. Saludos.

 
 

Clase java para recorrer y buscar registros de tabla (de Sql Server, Mysql o Postgres) con botones primero, anterior, siguiente y ultimo.

Clase java para recorrer y buscar registros de tabla de base de datos con botones primero, anterior, siguiente y ultimo. El objetivo de esta entrada de blog es mostrar una clase diseñada por mi para facilitar la navegacion por los registros de una tabla. Se me ocurrio esto debido a que en muchas ocasiones en los programas necesitamos recorrer los registros de una tabla con los tipicos botones:
Primero Permite ir al primer registro de la tabla.
Anterior Permite ir al anterior registro.
Siguiente Permite ir al siguiente registro.
Ultimo Permite ir al ultimo registro.

La siguiente imagen muestra un ejemplo clasico donde se requieren estos botones (los botones con flechas verdes):

Ventana con botones de navegacion de registros.
Ventana con botones de navegacion de registros.

Como se puede imaginar con ayuda de estos botones nos podemos colocar en cualquier registro de la tabla y una vez posicionados en el registro deseado se pueden usar otros botones para modificar o eliminar el registro. Bueno sin mas preambulos muestro el codigo de la clase:

GonzaBD.java
El truco de esta clase es almacenar en un array todos los campos llave de la tabla que se desee manipular (por cada tabla se debe crear un nuevo objeto de esta clase). Al llamar al metodo primero() con ayuda de una variable se accede al primer elemento del arreglo de llaves primarias. Al llamar al metodo ultimo() con ayuda de una variable se accede al ultimo elemento del arreglo de llaves primarias. Al llamar al metodo siguiente() con ayuda de una variable; si por ejemplo estamos en la fila 5, se accede al elemento 5 +1, del arreglo de llaves primarias. Despues se realiza un Select hacia la tabla y los datos quedan en un Objeto Resultset (llamado rs) que es local a esta clase, bueno a continuacion muestro el codigo:

/*
 *   Instituto Tecnologico de Zacatepec
 * Descripcion:  Clase que contiene metodos para recorrer los registros de una tabla 
 *						hacia el primer, anterior, siguiente o ultimo registro
 * Archivo: GonzaBD.java
 * author Gonzalo Silverio       gonzasilve@hotmail.com
 * fuente:  https://gonzasilve.wordpress.com
 */
import java.sql.*;


public class GonzaBD 
{
	String strSentenciaSQL = "";
	String strCadenaConexion = "";
	String strOrdenarPor = "";
	String strCampoLLave = "";
	String strTabla = "";
	String strArrayCamposLlave[];
	int intArrayCamposLlave[];
	
	//Los posibles tipos del campo llave son cadena y entero
	//Por defecto el campo llave es de tipo cadena
	String strTipoCampoLlave = "cadena";
	
	int intTotalRegistros = 0,intFilaActual = 0;	
	
	String strDriverMySQL 		="com.mysql.jdbc.Driver";
	String strDriverPostgres 	="org.postgresql.Driver";
	String strDriverSqlServer 	="net.sourceforge.jtds.jdbc.Driver";	
	
	String strManejador 		= "mysql";
	String strBaseDatos 		= "BD";
	String strServidor 		= "localhost";
	String strUsuario 		= "usuario";
	String strPassword		= "password";
	String strControlador 	= strDriverMySQL;
	String strPuerto			= "3306";
	
	private static Connection con = null;
	Statement st;
	ResultSet rs;
	
    public GonzaBD()
    {
    	
    }
    
    //se mueve a la primera fila y devuelve true si se pudo, false sino se pudo ir a la primera fila
    public  boolean  primero()
    {
      try
		{
			intFilaActual = 0;
			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);
				
			if( rs.next() )
				return true;
			
			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
    //se mueve a la anterior fila y devuelve true si se pudo, false sino se pudo ir a la anterior fila
    public  boolean  anterior()
    {
      try
		{
			intFilaActual--;
			if(intFilaActual<0)
				intFilaActual=0;
				
			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);
				
			if( rs.next() )
				return true;
			
			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
    //se mueve a la siguiente fila y devuelve true si se pudo, false sino se pudo ir a la siguiente fila
    public  boolean  siguiente()
    {
      try
		{
			intFilaActual++;
			if(intFilaActual>intTotalRegistros-1)
				intFilaActual=intTotalRegistros-1;

			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);
				
			if( rs.next() )
				return true;
			
			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
    //se mueve a la ultima fila y devuelve true si se pudo, false sino se pudo ir a la ultima fila
    public  boolean  ultimo()
    {
      try
		{
			intFilaActual = intTotalRegistros-1;

			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);
				
			if( rs.next() )
				return true;
			
			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
	 
	//Obtiene el controlador del manejador mysql o postgres
    public  String obtenerDriverManejador(String manejador)
    {
		if(manejador.equals("sqlserver"))							//Si el manejador es sql server
			return strDriverSqlServer;
		else if(manejador.equals("mysql"))							//Si el manejador es mysql
			return strDriverMySQL;
		else if(manejador.equals("postgres"))							//Si el manejador es postgres
			return strDriverPostgres;

			//en caso d k no sea ninguno devuelve el de MySQL			
			return strDriverMySQL;
    }
  	
	//Conecta a la BD con los datos por default
    public boolean conectarBD() throws SQLException
    {    
      try
		{
			return conectarServidor(strManejador,strServidor,strUsuario,strPassword,strBaseDatos,strControlador);
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    

	//Conecta a la BD con los datos del usuario, bd y password especificados, para los demas toma los k estan por default
    public boolean conectarBD(String usuario, String password, String BD )// throws SQLException
    {
    	boolean ress;
      try
		{
			strUsuario 		= usuario;
			strPassword 	= password;
			strBaseDatos 	= BD;
			ress = conectarServidor(strManejador,strServidor,usuario,password,BD,strControlador);
			return ress;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
    //permite especificar el campo por el que se van a ordenar los registros
    public  void ordenarPor(String campo)
    {
    	strOrdenarPor = campo;
    }
    
	//Conecta a la BD con los datos especificados, para los demas toma los k estan por default
    public boolean conectarBD(String usuario, String password, String BD, String manejador) //throws SQLException
    {
    	boolean ress;
      try
		{
			strControlador = obtenerDriverManejador(manejador);			
			strUsuario 		= usuario;
			strPassword 	= password;
			strBaseDatos 	= BD;
			strManejador 	= manejador;
			ress = conectarServidor(manejador,strServidor,usuario,password,BD,strControlador);
			return ress;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
	//Realiza una conexion a sqlserver, mysql o postgres con los datos especificados
    public boolean conectarServidor(String manejador,String servidor,String usuario,String pw,String bd, String driver) throws SQLException
    {
		if(manejador.equals("sqlserver"))							//Si el manejador es sql server
		{
		    try
		    {
		        Class.forName(driver);
		        strCadenaConexion = "jdbc:jtds:sqlserver://"+servidor+"/"+bd+";instance=SQLSERVEREXPRESS;";
		        con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
		        if (con == null )
		    			return false;
		        return true;
		    }
		    catch(SQLException sqlex)
		    {
		    		sqlex.printStackTrace();
		        	return false;
		    }
		    catch(Exception e)
		    {
		    		e.printStackTrace();
		        	return false;
		    }
		}            
    	else if(manejador.equals("mysql"))									//Si el manejador es mysql
    	{
           try
           {
		          Class.forName(driver);
		          strCadenaConexion = "jdbc:mysql://"+servidor+"/"+bd;
		          con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
		          if (con == null )		          	
		          	return false;
		          
		          return true;
            }
            catch(SQLException sqlex)
            {
            	sqlex.printStackTrace();
                return false;
            }
            catch(Exception e)
            {
            	e.printStackTrace();
            	return false;
            }
    	}
    	else if(manejador.equals("postgres"))							//Si el manejador es postgress
      {
          try
          {
              Class.forName(driver);
              strCadenaConexion = "jdbc:postgresql://"+servidor+":5432/"+bd;
              con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
              if (con == null )
          			return false;

              return true;
          }
          catch(SQLException sqlex)
          {

          		sqlex.printStackTrace();
              	return false;
          }
          catch(Exception e)
          {
          	e.printStackTrace();
              return false;
          }
      }

	    	return false;
    }
    
	//Ejecuta un SELECT y devuelve el Resultset con los resultados
	public ResultSet ejecutarConsulta(String cadSQ) throws SQLException
	{
		rs = null;
		if( ! strOrdenarPor.equals("") )
			cadSQ += " ORDER BY " +strOrdenarPor;
			
		try
		{
			rs = st.executeQuery(cadSQ);
			return rs;
       }
       catch(SQLException sqlex)
       {
       		sqlex.printStackTrace();
       		return rs;
       }

	}

	public  void obtenerCamposLlave()
	{
		obtenerCamposLlave(strTabla);
	}
	

	//Si el campo llave es de tipo entero guarda las llaves primarias en un arreglo de enteros
	//Si el campo llave es de tipo cadena guarda las llaves primarias en un arreglo de Strings
	public  void obtenerCamposLlave(String tabla)
	{
		int c=0;
		try
		{
			rs = ejecutarConsulta("SELECT * FROM " + tabla);
			while(rs.next())
				c++;
			intTotalRegistros = c;
			strArrayCamposLlave = new String[intTotalRegistros];
			intArrayCamposLlave = new int[intTotalRegistros];
			
			cerrar(rs);		//Cerrar consulta anterior
			//Ejecutar nuevamente la consulta
			rs = ejecutarConsulta("SELECT * FROM " + tabla);
			rs.next();		//Moverse al primer registro
			
			c=0;
			do
			{			//determina el tipo del campo llave y en base a eso guarda en el array correspondiente
				if( strTipoCampoLlave.equals("cadena") )				
					strArrayCamposLlave[c] = rs.getString(strCampoLLave);
				else
					intArrayCamposLlave[c] = rs.getInt(strCampoLLave);
					
				c++;
			}while( rs.next() );
			
		}
		catch(SQLException sqlex)
		{
       	sqlex.printStackTrace();
		}
		
	}

	
	// Cierra un objeto Resultset
	public static void cerrar(ResultSet rs)
	{	
		try
		{
			rs.close();
		} 
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
	
	// cierra un objeto Statemet
	public static void cerrar(Statement st)
	{
		try
		{
			st.close();
		} 
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

	// Cierra un objeto Connection
	public static void cerrar(Connection con)
	{	
		try
		{
			con.close();
		} 
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
	
	//Permite especificar cual es el campo llave de la tabla
	public  void setCampoLlave(String campo)
	{
		strCampoLLave = campo;
	}
	
	//Permite especificar cual es el campo llave y su tipo, de la tabla
	public  void setCampoLlave(String campo, String tipo)
	{
		strCampoLLave = campo;
		strTipoCampoLlave = tipo;
	}
	
	public void setTipoCampoLlave(String tipo)
	{
		strTipoCampoLlave = tipo;
	}
	
	//Especifica la tabla sobre la k se va a trabajar
	public  void setTabla(String tabla)
	{
		try
		{
			strTabla = tabla;
			st=con.createStatement();
		}
		catch(SQLException ex)
		{
			ex.printStackTrace();
		}

	}	
}	//Fin de la clase

Lo interesante de esta clase es que esta preparada para recorrrer los registros de tablas que esten creadas en cualquera de los manejadores SQL Server, MySQL o de Postgres, obviamente que los .jar de los JConnector de dichos DBMS deben estar copiados en C:\Program Files\Java\jdk1.6.0_23\jre\lib\ext, Lo que esta en negrita lo e resaltado debido a que la version del JVM puede cambiar segun la que tengas instalada. Los JConnector que e usado para probar esta clase son los siguientes (puedes dar click en el enlace para descargarlo sino lo tienes).
JConnector de SQL Server: jtds-1.2.5.jar
JConnector de Postgres: postgresql-9.1-901.jdbc4.jar
JConnector de MySQL: mysql-connector-java-5.1.18-bin.jar

Para ejemplificar el uso de la clase anterior e usado una tabla que esta en SQL Server. Los parametros de conexion son:
Manejador de Base de datos (DBMS): SQL Server 2005 Express
Base de datos: prueba
Tabla: tbl_alumnos
Usuario: sa
Password: 123456
El Script para crear la tabla alumnos en SQL Server es el siguiente (generado con el Microsoft SQL Server Management Studio):

USE [prueba]
GO
/****** Object:  Table [dbo].[tbl_alumnos]    Script Date: 12/28/2011 17:59:51 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[tbl_alumnos](
	[matricula] [int] NOT NULL,
	[nombre] [varchar](50) NULL,
	[apellidos] [varchar](100) NULL,
	[edad] [int] NULL,
	[peso] [decimal](10, 2) NULL,
	[sexo] [char](1) NULL,
 CONSTRAINT [PK__tbl_alumnos__6FBF826D] PRIMARY KEY CLUSTERED
(
	[matricula] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

La imagen de la tabla ya creada en SQL Server se ve asi:

Tabla Alumnos en SQL Server

DIAGRAMA UML DE LA CLASE gonzaBD

Diagrama UML de la clase gonzaBD

Diagrama UML de la clase gonzaBD

BREVE EXPLICACION DE LOS ATRIBUTOS DE LA CLASE gonzaBD:

Atributo Descripcion
intfilaActual Contiene un número que se usa como índice para acceder a una llave primaria dentro del arreglo strArrayCamposLlave o el arreglo strArrayCamposLlave (dependiendo de si la llave primaria es de tipo cadena o tipo entero, respectivamente). Este atributo contiene el número actual de fila-1.
strArrayCamposLlave[] Arreglo que contiene las llaves primarias de la tabla en caso de que el tipo de dato del campo llave sea Cadena.
intArrayCamposLlave[] Arreglo que contiene las llaves primarias de la tabla en caso de que el tipo de dato del campo llave sea Entero.
rs Contiene los datos de la fila actual mostrandose. Cada vez que se manda a llamar al método primero(), anterior(), siguiente() o ultimo() se realiza una consulta y este atributo (tipo Resultset) se actualiza con los campos de la nueva fila.

COMO SE USA LA CLASE gonzaBD
A continuacion voi a poner un fragmento de codigo con la intencion mostrar los pasos a realizar para usar correctamente la clase.

//Crear un objeto de esta clase
GonzaBD a = new GonzaBD();
//AHORA SE DEBE REALIZAR LO SIGUIENTE EN EL MISMO ORDEN…
//Primeramente se debe indicar especificar cual es la llave primaria de la tabla y su tipo
a.setCampoLlave("matricula","entero");
//Se de desea se puede indicar que si se desean ordenar los registros de la tabla por un campo, //este paso es opcional en todo caso sino se realiza, no se ordenan por ningún campo
a.ordenarPor("nombre");
//A continuación usamos un metodo sobrecargado para conectarse al DBMS, aquí es donde //indicamos a que manejador se debe accesar
a.conectarBD("sa","12345","pruebas","sqlserver");
//Una vez que ya estamos conectados se debe especificar la tabla que se va a manipular
a.setTabla("tbl_alumnos");
//Ahora se manda a llamar al método que rellena el arreglo de llaves primarias dentro de la clase; //dependiendo del tipo de dato del campo llave se rellena el arreglo de Strings o el arreglo de //enteros.
a.obtenerCamposLlave();
//Ahora ya se puede llamar a cualquiera de los métodos primero(), anterior(), siguiente() o ultimo()...

Despues de realizar lo anterior, para que el objeto rs se rellene con los datos de la primera fila se invoca al metodo:
a.primero();
Después de que se invoco ese metodo, el atributo rs de la clase gonzaBD se quedara con los datos de la fila 1. Supongamos que la tabla “alumnos”contiene las siguientes filas, rs apuntara a la fila:

El atributo rs esta en la posicion de la primera fila.

El atributo rs esta en la posicion de la primera fila.

Si inmediatamente despues se llama al método siguiente()
a.siguiente();
El atributo rs apuntara al siguiente registro despues del primero, es decir rs apuntara a la fila:

El atributo rs apunta a los datos de la segunda fila

El atributo rs apunta a los datos de la segunda fila

Y asi sucesivamente, una observación: si te fijas en el codigo de los metodos (siguiente() y anterior()) cuando se ha llegado a la ultima fila, es decir, si rs apunta al registro 4 y se ejecuta una llamada al método siguiente() (se intenta accesar una fila después de la ultima); dicho método contiene un ‘candado’ para detectar eso y siempre dejara a rs apuntando al ultimo registro. El método anterior() igualmente tiene esa precaucion y siempre que se intente accesar a un registro antes del primero automáticamente moverá a rs para que apunte a la primera fila. De esta manera no es posible sobrepasar los limites (inferior ni superior) de filas de la tabla que se este manipulando.

Finalmente Para ilustrar el uso de la clase gonzaBD anterior he creado una ventana muy basica.

JfrPrincipal.java
Esta clase crea una ventana de formulario con 6 campos y los 4 botones; primero, anterior, siguiente y ultimo en la parte inferior de dicha ventana. Es la misma clase que utilice para ilustrar como usar ventanas de formulario en Java, pero la he modificado con algunos campos mas. Bueno ahora muestro el codigo:

/*
 *   Instituto Tecnologico de Zacatepec
 * Descripcion:  Clase que crea una GUI para ilustrar el uso de la clase GonzaBD
 * Archivo: JfrPrincipal.java
 * author: Gonzalo Silverio       gonzasilve@hotmail.com
 * fuente:  https://gonzasilve.wordpress.com
 */

import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

//Se usara para cambiar los Margenes de los botones
import java.awt.Insets;

//Para Manejo de BD
import java.sql.*;

public class JfrPrincipal extends JFrame
{
	//Campos de texto y sus etiquetas 
	JLabel jlbMatricula;    JTextField  jtfMatricula;
	JLabel jlbNombre;       JTextField  jtfNombre;
	JLabel jlbApellidos;    JTextField  jtfApellidos;
	JLabel jlbEdad;         JTextField  jtfEdad;
	JLabel jlbPeso;         JTextField  jtfPeso;
	JLabel jlbSexo;         JComboBox   jcbSexo;
	
	//Botones de navegacion de los registros
	JButton btnPrimero;
	JButton btnAnterior;
	JButton btnSiguiente;
	JButton btnUltimo;
	
	Box boxVCamposVentana;   //Contiene todo los campos de texto (con su respectiva etiqueta)
	JPanel panBotones;      //Contiene los botones Guardar y Cancelar
	
	//Objeto de la clase que nos ayuda a navegar por los registros de la tabla
	GonzaBD bd = new GonzaBD();
	
	JfrPrincipal(String strTitulo, int intAncho, int intAlto)
	{
		super(strTitulo);
		this.setSize(intAncho, intAlto);
		this.setResizable(false);		//Ventana no redimensionable
		this.setLocationRelativeTo(null);       //Centrar ventana en pantalla
		
		//Box vertical por que los botones van a estar abajo
		Box boxVContenidoVerticalVentana = Box.createVerticalBox();
		crearCamposVentana();
		crearBotones();
		//Espacio del borde superior de la ventana al primer Campo
		boxVContenidoVerticalVentana.add(Box.createVerticalStrut(30));
		boxVContenidoVerticalVentana.add(boxVCamposVentana);
		//Espacio entre el ultimo campo (sexo) y los botones Guardar y Cancelar
		boxVContenidoVerticalVentana.add(Box.createVerticalStrut(20));
		boxVContenidoVerticalVentana.add(panBotones);
		
		this.add(boxVContenidoVerticalVentana);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	  
	  //Conecta la Base de datos
		conectarBD();
		bd.primero();		//Posicionarse en el primer registro
		rellenarCampos();		//Rellenar los campos con los datos del primer registro
		
		//ASIGNAR UN ESCUCHADOR PARA CADA BOTON DE NAVEGACION
		//Boton Primero
		btnPrimero.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.primero();
				rellenarCampos();
			}
		});
		//Boton Anterior
		btnAnterior.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.anterior();
				rellenarCampos();
			}
		});
		//Boton Siguiente
		btnSiguiente.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.siguiente();
				rellenarCampos();
			}
		});
		//Boton Ultimo
		btnUltimo.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.ultimo();
				rellenarCampos();
			}
		});
		  	
        	
	}		//Fin del constructor

	//Crea los campos de la ventana (cada caja tiene su correspondiente etiqueta)
    private void crearCamposVentana()
    {
        Box boxHMatricula =  Box.createHorizontalBox();        
        jlbMatricula = new JLabel("Matricula ");   jtfMatricula = new JTextField(15);
        boxHMatricula.add(Box.createHorizontalStrut(20));
        boxHMatricula.add(jlbMatricula);
        boxHMatricula.add(Box.createHorizontalStrut(14));
        boxHMatricula.add(jtfMatricula);
        JPanel panMatricula =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panMatricula.add(boxHMatricula);

        Box boxHNombre =  Box.createHorizontalBox();
        jlbNombre = new JLabel("Nombre ");   jtfNombre = new JTextField(15);
        boxHNombre.add(Box.createHorizontalStrut(20));
        boxHNombre.add(jlbNombre);
        boxHNombre.add(Box.createHorizontalStrut(20));
        boxHNombre.add(jtfNombre);
        JPanel panNombre =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panNombre.add(boxHNombre);

        Box boxHApellidos =  Box.createHorizontalBox();
        jlbApellidos = new JLabel("Apellidos ");   jtfApellidos = new JTextField(15);
        boxHApellidos.add(Box.createHorizontalStrut(20));
        boxHApellidos.add(jlbApellidos);
        boxHApellidos.add(Box.createHorizontalStrut(11));
        boxHApellidos.add(jtfApellidos);
        JPanel panApellidos =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panApellidos.add(boxHApellidos);

        Box boxHEdad =  Box.createHorizontalBox();
        jlbEdad = new JLabel("Edad ");   jtfEdad = new JTextField(15);
        boxHEdad.add(Box.createHorizontalStrut(20));
        boxHEdad.add(jlbEdad);
        boxHEdad.add(Box.createHorizontalStrut(40));
        boxHEdad.add(jtfEdad);
        JPanel panEdad =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panEdad.add(boxHEdad);
        
        Box boxHPeso =  Box.createHorizontalBox();
        jlbPeso = new JLabel("Peso ");   jtfPeso = new JTextField(15);
        boxHPeso.add(Box.createHorizontalStrut(20));
        boxHPeso.add(jlbPeso);
        boxHPeso.add(Box.createHorizontalStrut(40));
        boxHPeso.add(jtfPeso);
        JPanel panPeso =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panPeso.add(boxHPeso);

        Box boxHSexo =  Box.createHorizontalBox();
        jlbSexo = new JLabel("Sexo ");   jcbSexo = new JComboBox();
        jcbSexo.addItem("Masculino");
        jcbSexo.addItem("Femenino");
        boxHSexo.add(Box.createHorizontalStrut(20));
        boxHSexo.add(jlbSexo);
        boxHSexo.add(Box.createHorizontalStrut(40));
        boxHSexo.add(jcbSexo);
        JPanel panSexo =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panSexo.add(boxHSexo);

        boxVCamposVentana = Box.createVerticalBox();
        boxVCamposVentana.add(panMatricula);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panNombre);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panApellidos);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panEdad);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panPeso);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panSexo);
    }

    private void crearBotones()
    {
        Box boxHBotones = Box.createHorizontalBox();
        
        btnPrimero = new JButton("|< Primero");
        btnAnterior = new JButton("< Anterior");
        btnSiguiente = new JButton("Siguiente >");
        btnUltimo = new JButton("Ultimo >|");
        //Cambiar los margenes de los botones
        			//Insets(margen_sup, margen_izq, margen_inf, margen_der)
        btnPrimero.setMargin(new Insets(0, 2, 0, 2));
        btnAnterior.setMargin(new Insets(0, 2, 0, 2));
        btnSiguiente.setMargin(new Insets(0, 2, 0, 2));
        btnUltimo.setMargin(new Insets(0, 2, 0, 2));
        
        boxHBotones.add(btnPrimero);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnAnterior);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnSiguiente);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnUltimo);
        
        panBotones =  new JPanel(new FlowLayout(FlowLayout.CENTER) );
        panBotones.add(boxHBotones);
    }
	//Conecta con la BD y devuelve true si se conecto correctamente
	//false en cualquiero otro caso
	public boolean conectarBD()
	{
		// Especificar cual es la llave primaria de la tabla y su tipo
		bd.setCampoLlave("matricula","entero");
    	bd.ordenarPor("nombre");	//Ordena los registros de la tabla por este campo
		
		//Conecta con el usuario, pass, BD y dbms (manejador) especificados
		bd.conectarBD("sa","12345","pruebas","sqlserver");
		
    	//especifica la tabla sobre la que se va a manipular
    	bd.setTabla("tbl_alumnos");
    	//Dentro del objeto bd rellena un arreglo con las llaves 
    	//primarias de la tabla que se esta manipulando
		bd.obtenerCamposLlave();
		
		return true;
	}
	
	//Rellena los campos de texto con los datos del registro actual
    public void rellenarCampos()
    {
		try
		{
    		jtfMatricula.setText(aCadena(bd.rs.getInt("matricula")));
    		jtfNombre.setText(bd.rs.getString("nombre").trim ());
    		jtfApellidos.setText(bd.rs.getString("apellidos").trim ());
    		jtfEdad.setText(aCadena(bd.rs.getInt("edad")));
    		jtfPeso.setText(aCadena(bd.rs.getFloat("peso")));
    		jcbSexo.setSelectedItem( bd.rs.getString("sexo").equals("f") ? "Femenino" : "Masculino" );
    		
    		this.setTitle("Alumno "+(bd.intFilaActual+1)+" de "+bd.intTotalRegistros);
		}
		catch( SQLException ex )
		{
			ex.printStackTrace();
		}
    }
    
    //Recibe un numero entero y lo devuelve como Cadena (String)
    private String aCadena(int num)
    {
    	return String.valueOf(num);
    }
    
    //Recibe un numero decimal y lo devuelve como Cadena (String)
    private String aCadena(float num)
    {
    	return String.valueOf(num);
    }
    
    private void mostrar()
    {
        this.setVisible(true);
    }

    public static void main(String args[])
    {
        JfrPrincipal prueba1 = new JfrPrincipal("Recorrer registros de SQL Server en Java",400,400);
        prueba1.mostrar();
    }
}

Y aqui una imagen de la ejecucion:

Ejecucion del ejemplo: Mostrando la tabla alumnos

Ejecucion del ejemplo: Mostrando la tabla alumnos

A diferencia de la otra entrada de blog anterior a esta, ahora se pueden realizar busquedas e igualmente se pueden recorrer los resultados con ayuda de la misma clase. La busqueda se puede realizar por matricula, nombre o por genero (sexo). Por ejemplo en caso de que decidamos buscar en los nombres de los alumnos la cadena ‘ar’, debemos marcar el radio nombre, escribir en la cajita ‘ar’ y dar clic en el boton Buscar en este caso se encontraron 4 resultados, como se muestra en la siguiente imagen:

Buscando por nombre a un alumno

Buscando por nombre a un alumno

Observa como automaticamente se desactivan los controles de busqueda y se muestran los resultados; los cuales tambien se pueden recorrer con los mismos botones de Primero, Anterior, Siguiente y Ultimo. Ademas el texto del boton Buscar cambia y ahora ese boton permite terminar la Busqueda. Al dar click en el boton Fin Busqueda se muestran nuevamente todos los alumnos de la tabla y se despliega el que estaba mostrandose antes de hacer la busqueda. Por ultimo muestro otro pantallazo de una busqueda por Sexo:

Buscando alumnos por sexo

Buscando alumnos por sexo

Como decia anteriormente lo interesante es que si ahora deseamos que la tabla alumnos este creada en MySQL o Postgres, entonces la creamos en dicho manejador (con ayuda del script que puse mas arriba; estan los nombres de los campos y su tipo) y en la linea 402 de la clase JfrPrincipal.java, cambiamos los parametros de Conexion (usuario,pass,bd, manejador) de dicho manejador, la clase automaticamente usara el Driver adecuado y se conectara a dicho DBMS sin problemas.

Sin querer se hizo un poco largo este ejemplo, pero no era para mas, espero haber sido lo suficiente explicito y no haber dejado muchas dudas, los ya avanzados en Java supongo que mi codigo lo habran digerido sin problemas y los que empiezan de todas maneras pregunten sin compromiso, les aseguro que yo tambien soy un novato y seguro hay alguna manera mas fina y elegante de hacer esto del recorrido de registros, solo es una idea. . Y es que a la clase GonzaBD.java la simplifique y le quite mucho codigo para que quedara simple y sencilla de entender ya que mi version original tiene muchos mas metodos para realizar las cuatro Operaciones SQL de manera mas simple (INSERT, DELETE, UPDATE, SELECT), pero me reservo el codigo y posiblemente mas adelante lo libere en este mismo blog, por ahora creo que seria demasiado y requeria mas tiempo para explicarlo y estoy muy ocupado estod dias.

Bueno no me queda mas que decir hasta pronto y si a alguien le interesan los fuentes basta con pedirlos y se los envio, hasta pronto y gracias x visitar.

Clase java para recorrer registros de tabla SQL Server con botones primero, anterior, siguiente y ultimo

Clase java para recorrer registros de tabla SQL Server con botones primero, anterior, siguiente y ultimo. El objetivo de esta entrada de blog es mostrar una clase diseñada por mi para facilitar la navegacion por los registros de una tabla. Se me ocurrio esto debido a que en muchas ocasiones en los programas necesitamos recorrer los registros de una tabla con los tipicos botones:
Primero Permite ir al primer registro de la tabla.
Anterior Permite ir al anterior registro.
Siguiente Permite ir al siguiente registro.
Ultimo Permite ir al ultimo registro.

La siguiente imagen muestra un ejemplo clasico donde se requieren estos botones (los botones con flechas verdes):

Ventana con botones de navegacion de registros.
Ventana con botones de navegacion de registros.

Como se puede imaginar con ayuda de estos botones nos podemos colocar en cualquier registro de la tabla y una vez posicionados en el registro deseado se pueden usar otros botones para modificar o eliminar el registro. Bueno sin mas preambulos muestro el codigo de la clase:

GonzaBD.java
El truco de esta clase es almacenar en un array todos los campos llave de la tabla que se desee manipular (por cada tabla se debe crear un nuevo objeto de esta clase). Al llamar al metodo primero() con ayuda de una variable se accede al primer elemento del arreglo de llaves primarias. Al llamar al metodo ultimo() con ayuda de una variable se accede al ultimo elemento del arreglo de llaves primarias. Al llamar al metodo siguiente() con ayuda de una variable; si por ejemplo estamos en la fila 5, se accede al elemento 5 +1, del arreglo de llaves primarias. Despues se realiza un Select hacia la tabla y los datos quedan en un Objeto Resultset (llamado rs) que es local a esta clase. Bueno a continuacion muestro el codigo:

/*
 *   Instituto Tecnologico de Zacatepec
 * Descripcion:  Clase que contiene metodos para recorrer los registros de una tabla
 *						hacia el primer, anterior, siguiente o ultimo registro
 * Archivo: GonzaBD.java
 * author Gonzalo Silverio       gonzasilve@hotmail.com
 * fuente:  https://gonzasilve.wordpress.com
 */
import java.sql.*;

public class GonzaBD
{
	String strSentenciaSQL = "";
	String strCadenaConexion = "";
	String strOrdenarPor = "";
	String strCampoLLave = "";
	String strTabla = "";
	String strArrayCamposLlave[];
	int intArrayCamposLlave[];

	//Los posibles tipos del campo llave son cadena y entero
	//Por defecto el campo llave es de tipo cadena
	String strTipoCampoLlave = "cadena";

	int intTotalRegistros = 0,intFilaActual = 0;

	String strDriverMySQL 		="com.mysql.jdbc.Driver";
	String strDriverPostgres 	="org.postgresql.Driver";
	String strDriverSqlServer 	="net.sourceforge.jtds.jdbc.Driver";

	String strManejador 		= "mysql";
	String strBaseDatos 		= "BD";
	String strServidor 		= "localhost";
	String strUsuario 		= "usuario";
	String strPassword		= "password";
	String strControlador 	= strDriverMySQL;
	String strPuerto			= "3306";

	private static Connection con = null;
	Statement st;
	ResultSet rs;

    public GonzaBD()
    {

    }

    //se mueve a la primera fila y devuelve true si se pudo, false sino se pudo ir a la primera fila
    public  boolean  primero()
    {
      try
		{
			intFilaActual = 0;
			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);

			if( rs.next() )
				return true;

			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

    //se mueve a la anterior fila y devuelve true si se pudo, false sino se pudo ir a la anterior fila
    public  boolean  anterior()
    {
      try
		{
			intFilaActual--;
			if(intFilaActual<0)
				intFilaActual=0;

			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);

			if( rs.next() )
				return true;

			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

    //se mueve a la siguiente fila y devuelve true si se pudo, false sino se pudo ir a la siguiente fila
    public  boolean  siguiente()
    {
      try
		{
			intFilaActual++;
			if(intFilaActual>intTotalRegistros-1)
				intFilaActual=intTotalRegistros-1;

			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);

			if( rs.next() )
				return true;

			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

    //se mueve a la ultima fila y devuelve true si se pudo, false sino se pudo ir a la ultima fila
    public  boolean  ultimo()
    {
      try
		{
			intFilaActual = intTotalRegistros-1;

			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);

			if( rs.next() )
				return true;

			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

	//Obtiene el controlador del manejador mysql o postgres
    public  String obtenerDriverManejador(String manejador)
    {
		if(manejador.equals("sqlserver"))							//Si el manejador es sql server
			return strDriverSqlServer;
		else if(manejador.equals("mysql"))							//Si el manejador es mysql
			return strDriverMySQL;
		else if(manejador.equals("postgres"))							//Si el manejador es postgres
			return strDriverPostgres;

			//en caso d k no sea ninguno devuelve el de MySQL
			return strDriverMySQL;
    }

	//Conecta a la BD con los datos por default
    public boolean conectarBD() throws SQLException
    {
      try
		{
			return conectarServidor(strManejador,strServidor,strUsuario,strPassword,strBaseDatos,strControlador);
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

	//Conecta a la BD con los datos especificados
    public boolean conectarBD(String usuario, String password, String BD, String manejador) //throws SQLException
    {
    	boolean ress;
      try
		{
			strControlador = obtenerDriverManejador(manejador);
			strUsuario 		= usuario;
			strPassword 	= password;
			strBaseDatos 	= BD;
			strManejador 	= manejador;
			ress = conectarServidor(manejador,strServidor,usuario,password,BD,strControlador);
			return ress;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

	//Conecta a la BD con los datos del usuario, bd y password especificados, para los demas toma los k estan por default
    public boolean conectarBD(String usuario, String password, String BD )// throws SQLException
    {
    	boolean ress;
      try
		{
			strUsuario 		= usuario;
			strPassword 	= password;
			strBaseDatos 	= BD;
			ress = conectarServidor(strManejador,strServidor,usuario,password,BD,strControlador);
			return ress;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

    //permite especificar el campo por el que se van a ordenar los registros
    public  void ordenarPor(String campo)
    {
    	strOrdenarPor = campo;
    }

	//Realiza una conexion a sqlserver, mysql o postgres con los datos especificados
    public boolean conectarServidor(String manejador,String servidor,String usuario,String pw,String bd, String driver) throws SQLException
    {
		if(manejador.equals("sqlserver"))							//Si el manejador es sql server
		{
		    try
		    {
		        Class.forName(driver);
		        strCadenaConexion = "jdbc:jtds:sqlserver://"+servidor+"/"+bd+";instance=SQLSERVEREXPRESS;";
		        con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
		        if (con == null )
		    			return false;
		        return true;
		    }
		    catch(SQLException sqlex)
		    {
		    		sqlex.printStackTrace();
		        	return false;
		    }
		    catch(Exception e)
		    {
		    		e.printStackTrace();
		        	return false;
		    }
		}
    	else if(manejador.equals("mysql"))									//Si el manejador es mysql
    	{
           try
           {
		          Class.forName(driver);
		          strCadenaConexion = "jdbc:mysql://"+servidor+"/"+bd;
		          con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
		          if (con == null )
		          	return false;

		          return true;
            }
            catch(SQLException sqlex)
            {
            	sqlex.printStackTrace();
                return false;
            }
            catch(Exception e)
            {
            	e.printStackTrace();
            	return false;
            }
    	}
    	else if(manejador.equals("postgres"))							//Si el manejador es postgress
      {
          try
          {
              Class.forName(driver);
              strCadenaConexion = "jdbc:postgresql://"+servidor+":5432/"+bd;
              con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
              if (con == null )
          			return false;

              return true;
          }
          catch(SQLException sqlex)
          {

          		sqlex.printStackTrace();
              	return false;
          }
          catch(Exception e)
          {
          	e.printStackTrace();
              return false;
          }
      }

	    	return false;
    }

	//Ejecuta un SELECT y devuelve el Resultset con los resultados
	public ResultSet ejecutarConsulta(String cadSQ) throws SQLException
	{
		rs = null;
		if( ! strOrdenarPor.equals("") )
			cadSQ += " ORDER BY " +strOrdenarPor;

		try
		{
			rs = st.executeQuery(cadSQ);
			return rs;
       }
       catch(SQLException sqlex)
       {
       		sqlex.printStackTrace();
       		return rs;
       }

	}

	public  void obtenerCamposLlave()
	{
		obtenerCamposLlave(strTabla);
	}

	//Si el campo llave es de tipo entero guarda los campos llave en un arreglo de enteros
	//Si el campo llave es de tipo cadena guarda los campos llave en un arreglo de Strings
	public  void obtenerCamposLlave(String tabla)
	{
		int c=0;
		try
		{
			rs = ejecutarConsulta("SELECT * FROM " + tabla);
			while(rs.next())
				c++;
			intTotalRegistros = c;
			strArrayCamposLlave = new String[intTotalRegistros];
			intArrayCamposLlave = new int[intTotalRegistros];

			cerrar(rs);		//Cerrar consulta anterior
			//Ejecutar nuevamente la consulta
			rs = ejecutarConsulta("SELECT * FROM " + tabla);
			rs.next();		//Moverse al primer registro

			c=0;
			do
			{			//determina el tipo del campo llave y en base a eso guarda en el array correspondiente
				if( strTipoCampoLlave.equals("cadena") )
					strArrayCamposLlave[c] = rs.getString(strCampoLLave);
				else
					intArrayCamposLlave[c] = rs.getInt(strCampoLLave);

				c++;
			}while( rs.next() );

		}
		catch(SQLException sqlex)
		{
       	sqlex.printStackTrace();
		}

	}

	// Cierra un objeto Resultset
	public static void cerrar(ResultSet rs)
	{
		try
		{
			rs.close();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

	// cierra un objeto Statemet
	public static void cerrar(Statement st)
	{
		try
		{
			st.close();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

	// Cierra un objeto Connection
	public static void cerrar(Connection con)
	{
		try
		{
			con.close();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

	//Permite especificar cual es el campo llave de la tabla
	public  void setCampoLlave(String campo)
	{
		strCampoLLave = campo;
	}

	//Permite especificar cual es el campo llave y su tipo, de la tabla
	public  void setCampoLlave(String campo, String tipo)
	{
		strCampoLLave = campo;
		strTipoCampoLlave = tipo;
	}

	public void setTipoCampoLlave(String tipo)
	{
		strTipoCampoLlave = tipo;
	}

	//Especifica la tabla sobre la k se va a trabajar
	public  void setTabla(String tabla)
	{
		try
		{
			strTabla = tabla;
			st=con.createStatement();
		}
		catch(SQLException ex)
		{
			ex.printStackTrace();
		}

	}
}	//Fin de la clase

Como se puede observar en la linea 229 de la clase GonzaBD.java estoy usando un nombre de instancia llamado SQLSERVEREXPRESS Esta clase se podria editar para recibir tambien como parametro el nombre de la instancia de SQL Server que se desee utilizar, se queda de tarea.

Lo interesante de esta clase es que esta preparada para recorrrer los registros de tablas que esten creadas en cualquera de los manejadores SQL Server, MySQL o de Postgres, obviamente que los .jar de los JConnector de dichos DBMS  deben estar copiados en C:\Program Files\Java\jdk1.6.0_23\jre\lib\ext, Lo que esta en negrita lo e resaltado debido a que la version del JVM puede cambiar segun la que tengas instalada. Los JConnector que e usado para probar esta clase son los siguientes (puedes dar click en el enlace para descargarlo sino lo tienes).
JConnector de SQL Server: jtds-1.2.5.jar
JConnector de Postgres: postgresql-9.1-901.jdbc4.jar
JConnector de MySQL: mysql-connector-java-5.1.18-bin.jar

Para ejemplificar el uso de la clase anterior e usado una tabla que esta en SQL Server. Los parametros de conexion son:
Manejador de Base de datos (DBMS): SQL Server 2005 Express
Base de datos: prueba
Tabla: alumnos
Usuario: sa
Password: root

El Script para crear la tabla alumnos en SQL Server es el siguiente:

create table alumnos(matricula int, nombre char(50), apellidos char(100), edad int, peso decimal(10,2),sexo char(1), PRIMARY KEY(matricula) );

La imagen de la tabla ya creada en SQL Server se ve asi:

Tabla alumnos en SQL Server

Tabla alumnos en SQL Server

DIAGRAMA UML DE LA CLASE gonzaBD

Diagrama UML de la clase gonzaBD

Diagrama UML de la clase gonzaBD

BREVE EXPLICACION DE LOS ATRIBUTOS DE LA CLASE gonzaBD:

Atributo Descripcion
intfilaActual Contiene un número que se usa como índice para acceder a una llave primaria dentro del arreglo strArrayCamposLlave o el arreglo strArrayCamposLlave (dependiendo de si la llave primaria es de tipo cadena o tipo entero, respectivamente). Este atributo contiene el número actual de fila-1.
strArrayCamposLlave[] Arreglo que contiene las llaves primarias de la tabla en caso de que el tipo de dato del campo llave sea Cadena.
intArrayCamposLlave[] Arreglo que contiene las llaves primarias de la tabla en caso de que el tipo de dato del campo llave sea Entero.
rs Contiene los datos de la fila actual mostrandose. Cada vez que se manda a llamar al método primero(), anterior(), siguiente() o ultimo() se realiza una consulta y este atributo (tipo Resultset) se actualiza con los campos de la nueva fila.

COMO SE USA LA CLASE gonzaBD
A continuacion voi a poner un fragmento de codigo con la intencion mostrar los pasos a realizar para usar correctamente la clase.

//Crear un objeto de esta clase
GonzaBD a = new GonzaBD();
//AHORA SE DEBE REALIZAR LO SIGUIENTE EN EL MISMO ORDEN…
//Primeramente se debe indicar especificar cual es la llave primaria de la tabla y su tipo
a.setCampoLlave("matricula","entero");
//Se de desea se puede indicar que si se desean ordenar los registros de la tabla por un campo, //este paso es opcional en todo caso sino se realiza, no se ordenan por ningún campo
a.ordenarPor("nombre");
//A continuación usamos un metodo sobrecargado para conectarse al DBMS, aquí es donde //indicamos a que manejador se debe accesar
a.conectarBD("sa","root","prueba","sqlserver");
//Una vez que ya estamos conectados se debe especificar la tabla que se va a manipular
a.setTabla("alumnos");
//Ahora se manda a llamar al método que rellena el arreglo de llaves primarias dentro de la clase; //dependiendo del tipo de dato del campo llave se rellena el arreglo de Strings o el arreglo de //enteros.
a.obtenerCamposLlave();
//Ahora ya se puede llamar a cualquiera de los métodos primero(), anterior(), siguiente() o ultimo()... 

Despues de realizar lo anterior, para que el objeto rs se rellene con los datos de la primera fila se invoca al metodo:
a.primero();
Después de que se invoco ese metodo, el atributo rs de la clase gonzaBD se quedara con los datos de la fila 1. Supongamos que la tabla “alumnos” contiene las siguientes filas, rs apuntara a la fila:

El atributo rs esta en la posicion de la primera fila.

El atributo rs esta en la posicion de la primera fila.

Si inmediatamente despues se llama al método siguiente()
a.siguiente();
El atributo rs apuntara al siguiente registro despues del primero, es decir rs apuntara a la fila:

El atributo rs apunta a los datos de la segunda fila

El atributo rs apunta a los datos de la segunda fila

Y asi sucesivamente, una observación: si te fijas en el codigo de los metodos (siguiente() y anterior()) cuando se ha llegado a la ultima fila, es decir, si rs apunta al registro 4 y se ejecuta una llamada al método siguiente() (se intenta accesar una fila después de la ultima); dicho método contiene un ‘candado’ para detectar eso y siempre dejara a rs apuntando al ultimo registro. El método anterior() igualmente tiene esa precaucion y siempre que se intente accesar a un registro antes del primero automáticamente moverá a rs para que apunte a la primera fila. De esta manera no es posible sobrepasar los limites (inferior ni superior) de filas de la tabla que se este manipulando.

Finalmente Para ilustrar el uso de la clase gonzaBD anterior he creado una ventana muy basica.

JfrPrincipal.java
Esta clase crea una ventana de formulario con 6 campos y los 4 botones; primero, anterior, siguiente y ultimo en la parte inferior de dicha ventana. Es la misma clase que utilice para ilustrar como usar ventanas de formulario en Java, pero la he modificado y adaptado para este ejemplo mas elaborado. Bueno ahora muestro el codigo:

/*
 *   Instituto Tecnologico de Zacatepec
 * Descripcion:  Clase que crea una GUI para ilustrar el uso de la clase EasyBD
 * Archivo: JfrPrincipal.java
 * author: Gonzalo Silverio       gonzasilve@hotmail.com
 * fuente:  https://gonzasilve.wordpress.com
 */

import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

//Se usara para cambiar los Margenes de los botones
import java.awt.Insets;

//Para Manejo de BD
import java.sql.*;

public class JfrPrincipal extends JFrame
{
	//Campos de texto y sus etiquetas 
	JLabel jlbMatricula;    JTextField  jtfMatricula;
	JLabel jlbNombre;       JTextField  jtfNombre;
	JLabel jlbApellidos;    JTextField  jtfApellidos;
	JLabel jlbEdad;         JTextField  jtfEdad;
	JLabel jlbPeso;         JTextField  jtfPeso;
	JLabel jlbSexo;         JComboBox   jcbSexo;
	
	//Botones de navegacion de los registros
	JButton btnPrimero;
	JButton btnAnterior;
	JButton btnSiguiente;
	JButton btnUltimo;
	
	Box boxVCamposVentana;   //Contiene todo los campos de texto (con su respectiva etiqueta)
	JPanel panBotones;      //Contiene los botones Guardary Cancelar
	
	//Objeto de la clase que nos ayuda a navegar por los registros de la tabla
	GonzaBD bd = new GonzaBD();
	
	JfrPrincipal(String strTitulo, int intAncho, int intAlto)
	{
		super(strTitulo);
		this.setSize(intAncho, intAlto);
		this.setResizable(false);		//Ventana no redimensionable
		this.setLocationRelativeTo(null);       //Centrar ventana en pantalla
		
		//Box vertical por que los botones van a estar abajo
		Box boxVContenidoVerticalVentana = Box.createVerticalBox();
		crearCamposVentana();
		crearBotones();
		//Espacio del borde superior de la ventana al primer Campo
		boxVContenidoVerticalVentana.add(Box.createVerticalStrut(30));
		boxVContenidoVerticalVentana.add(boxVCamposVentana);
		//Espacio entre el ultimo campo (sexo) y los botones Guardar y Cancelar
		boxVContenidoVerticalVentana.add(Box.createVerticalStrut(20));
		boxVContenidoVerticalVentana.add(panBotones);
		
		this.add(boxVContenidoVerticalVentana);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	  
	  //Conecta la Base de datos
		conectarBD();
		bd.primero();		//Posicionarse en el primer registro
		rellenarCampos();		//Rellenar los campos con los datos del primer registro
		
		//ASIGNAR UN ESCUCHADOR PARA CADA BOTON DE NAVEGACION
		//Boton Primero
		btnPrimero.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.primero();
				rellenarCampos();
			}
		});
		//Boton Anterior
		btnAnterior.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.anterior();
				rellenarCampos();
			}
		});
		//Boton Siguiente
		btnSiguiente.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.siguiente();
				rellenarCampos();
			}
		});
		//Boton Ultimo
		btnUltimo.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.ultimo();
				rellenarCampos();
			}
		});
		  	
        	
	}		//Fin del constructor

	//Crea los campos de la ventana (cada caja tiene su correspondiente etiqueta)
    private void crearCamposVentana()
    {
        Box boxHMatricula =  Box.createHorizontalBox();        
        jlbMatricula = new JLabel("Matricula ");   jtfMatricula = new JTextField(15);
        boxHMatricula.add(Box.createHorizontalStrut(20));
        boxHMatricula.add(jlbMatricula);
        boxHMatricula.add(Box.createHorizontalStrut(14));
        boxHMatricula.add(jtfMatricula);
        JPanel panMatricula =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panMatricula.add(boxHMatricula);

        Box boxHNombre =  Box.createHorizontalBox();
        jlbNombre = new JLabel("Nombre ");   jtfNombre = new JTextField(15);
        boxHNombre.add(Box.createHorizontalStrut(20));
        boxHNombre.add(jlbNombre);
        boxHNombre.add(Box.createHorizontalStrut(20));
        boxHNombre.add(jtfNombre);
        JPanel panNombre =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panNombre.add(boxHNombre);

        Box boxHApellidos =  Box.createHorizontalBox();
        jlbApellidos = new JLabel("Apellidos ");   jtfApellidos = new JTextField(15);
        boxHApellidos.add(Box.createHorizontalStrut(20));
        boxHApellidos.add(jlbApellidos);
        boxHApellidos.add(Box.createHorizontalStrut(11));
        boxHApellidos.add(jtfApellidos);
        JPanel panApellidos =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panApellidos.add(boxHApellidos);

        Box boxHEdad =  Box.createHorizontalBox();
        jlbEdad = new JLabel("Edad ");   jtfEdad = new JTextField(15);
        boxHEdad.add(Box.createHorizontalStrut(20));
        boxHEdad.add(jlbEdad);
        boxHEdad.add(Box.createHorizontalStrut(40));
        boxHEdad.add(jtfEdad);
        JPanel panEdad =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panEdad.add(boxHEdad);
        
        Box boxHPeso =  Box.createHorizontalBox();
        jlbPeso = new JLabel("Peso ");   jtfPeso = new JTextField(15);
        boxHPeso.add(Box.createHorizontalStrut(20));
        boxHPeso.add(jlbPeso);
        boxHPeso.add(Box.createHorizontalStrut(40));
        boxHPeso.add(jtfPeso);
        JPanel panPeso =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panPeso.add(boxHPeso);

        Box boxHSexo =  Box.createHorizontalBox();
        jlbSexo = new JLabel("Sexo ");   jcbSexo = new JComboBox();
        jcbSexo.addItem("Masculino");
        jcbSexo.addItem("Femenino");
        boxHSexo.add(Box.createHorizontalStrut(20));
        boxHSexo.add(jlbSexo);
        boxHSexo.add(Box.createHorizontalStrut(40));
        boxHSexo.add(jcbSexo);
        JPanel panSexo =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panSexo.add(boxHSexo);

        boxVCamposVentana = Box.createVerticalBox();
        boxVCamposVentana.add(panMatricula);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panNombre);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panApellidos);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panEdad);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panPeso);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panSexo);
    }

    private void crearBotones()
    {
        Box boxHBotones = Box.createHorizontalBox();
        
        btnPrimero = new JButton("|< Primero");
        btnAnterior = new JButton("< Anterior");
        btnSiguiente = new JButton("Siguiente >");
        btnUltimo = new JButton("Ultimo >|");
        //Cambiar los margenes de los botones
        			//Insets(margen_sup, margen_izq, margen_inf, margen_der)
        btnPrimero.setMargin(new Insets(0, 2, 0, 2));
        btnAnterior.setMargin(new Insets(0, 2, 0, 2));
        btnSiguiente.setMargin(new Insets(0, 2, 0, 2));
        btnUltimo.setMargin(new Insets(0, 2, 0, 2));
        
        boxHBotones.add(btnPrimero);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnAnterior);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnSiguiente);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnUltimo);
        
        panBotones =  new JPanel(new FlowLayout(FlowLayout.CENTER) );
        panBotones.add(boxHBotones);
    }
	//Conecta con la BD y devuelve true si se conecto correctamente
	//false en cualquiero otro caso
	public boolean conectarBD()
	{
		// Especificar cual es la llave primaria de la tabla y su tipo
		bd.setCampoLlave("matricula","entero");
    	bd.ordenarPor("nombre");	//Ordena los registros de la tabla por este campo
		
		//Conecta con el usuario, pass, BD y dbms (manejador) especificados
		bd.conectarBD("sa","root","prueba","sqlserver");
		
    	//especifica la tabla sobre la que se va a manipular
    	bd.setTabla("alumnos");
    	//Dentro del objeto bd rellena un arreglo con las llaves 
    	//primarias de la tabla que se esta manipulando
		bd.obtenerCamposLlave();
		
		return true;
	}
	
	//Rellena los campos de texto con los datos del registro actual
    public void rellenarCampos()
    {
		try
		{
    		jtfMatricula.setText(aCadena(bd.rs.getInt("matricula")));
    		jtfNombre.setText(bd.rs.getString("nombre").trim ());
    		jtfApellidos.setText(bd.rs.getString("apellidos").trim ());
    		jtfEdad.setText(aCadena(bd.rs.getInt("edad")));
    		jtfPeso.setText(aCadena(bd.rs.getFloat("peso")));
    		jcbSexo.setSelectedItem( bd.rs.getString("sexo").equals("f") ? "Femenino" : "Masculino" );
    		
    		this.setTitle("Alumno "+(bd.intFilaActual+1)+" de "+bd.intTotalRegistros);
		}
		catch( SQLException ex )
		{
			ex.printStackTrace();
		}
    }
    
    //Recibe un numero entero y lo devuelve como Cadena (String)
    private String aCadena(int num)
    {
    	return String.valueOf(num);
    }
    
    //Recibe un numero decimal y lo devuelve como Cadena (String)
    private String aCadena(float num)
    {
    	return String.valueOf(num);
    }
    
    private void mostrar()
    {
        this.setVisible(true);
    }

    public static void main(String args[])
    {
        JfrPrincipal prueba1 = new JfrPrincipal("Recorrer registros de SQL Server en Java",400,400);
        prueba1.mostrar();
    }
}

Y aqui una imagen de la ejecucion:

Ejecucion de la clase que recorre registros de tabla de SQL Server.

Ejecucion de la clase que recorre registros de tabla de SQL Server.

Como decia anteriormente lo interesante es que si ahora deseamos que la tabla alumnos este creada en MySQL o Postgres, entonces la creamos en dicho manejador (con ayuda del script que puse mas arriba) y en la linea 216 de la clase JfrPrincipal.java, cambiamos los parametros de Conexion (usuario,pass,bd, manejador) de dicho manejador, la clase automaticamente usara el Driver adecuado y se conectara a dicho DBMS sin problemas.

Sin querer se hizo un poco largo este ejemplo, pero no era para mas, espero haber sido lo suficiente explicito y no haber dejado muchas dudas, los ya avanzados en Java supongo que mi codigo lo habran digerido sin problemas y los que empiezan de todas maneras pregunten sin compromiso, les aseguro que yo tambien soy un novato y seguro hay alguna manera mas fina y elegante de hacer esto del recorrido de registros, solo es una idea. . Y es que a la clase GonzaBD.java la simplifique y le quite mucho codigo para que quedara simple y sencilla de entender ya que mi version original tiene muchos mas metodos para realizar las cuatro Operaciones SQL de manera mas simple (INSERT, DELETE, UPDATE, SELECT), pero me reservo el codigo y posiblemente mas adelante lo libere en este mismo blog, por ahora creo que seria demasiado y requeria mas tiempo para explicarlo y estoy en el fin de mi ultimo semestre de la carrera!!! poryectos por aqui, proyectos por allaa.

Bueno no me queda mas que decir hasta pronto y si a alguien le interesan los fuentes basta con pedirlos y se los envio, hasta pronto y gracias x visitar.

Como generar un PDF con datos de una tabla MySQL con ayuda de iText

Ejemplo muy sencillo donde se ilustra como generar un documento PDF con datos provenientes de una tabla creada en MySQL con la libreria iText. Bueno creo que el titulo de la entrada lo dice todo asi que no quiero ser redundante en el objetivo de esta practica de programacion.

El ejemplo consta de 3 archivos: CrearConexion.java, GenerarPDFEmpleados.java JfrPrincipal.java (a decir verdad tambien se usa una imagen (logo de mysql), pero puedes cambiarla por otra que quieras). Como en casi todos mis ejemplos, no voi a dar mucha explicacion debido a que mi objetivo es tener disponible el ejemplo de codigo. Primero que nada te muestro un diagrama para que veas en forma grafica y rapida la estructura del ejemplo:

Diagrama que muestra en forma grafica el ejemplo

Diagrama que muestra en forma grafica el ejemplo

A continuacion se explican brevemente los tres archivos de codigo a grandes rasgos:

JfrPrincipal
Clase que crea una interfaz grafica de usuario muy sencilla; la cual es una ventana con 2 JLabels, un JTextField y un JButton. Desde esta clase se hace una instancia de la clase GenerarPDFEmpleados.java, la cual es la que realmente genera el PDF con ayuda de la libreria iText. En el codigo se muestran los comentarios correspondiente explicando casi todo…

/*
		Instituto Tecnologico de Zacatepec, Mor.
Descripcion:  Clase que crea una ventana con un boton que al darle clic
					genera el PDF de una tabla de MySQL.
Autor:  			Gonzalo Silverio   gonzasilve@gmail.com
Archivo: 		JfrPrincipal.java
*/

import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.event.*;

public class JfrPrincipal extends JFrame
{
	String strTituloPDF = "INSTItuTO TEcnologico de zacatepec";
	String strNombrePDF = "pdf_tabla_Empleados.pdf";
	JTextField jtfNombrePDF;
	
	//Constructor
	JfrPrincipal(String titulo, int ancho, int alto)
	{
		//Establecer titulo, tamanio y posicion en la pantalla
		super(titulo);
		setSize(ancho,alto);
		setLocationRelativeTo(null);	//centrado
		//Rotulo principal de la ventana
		JLabel lblTitulo = new JLabel("Generar un PDF desde Java");
		JPanel panTitulo = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panTitulo.add(lblTitulo);
		
		//Crea campo de texto para especificar el nombre del PDF
		JLabel lblNombrePDF = new JLabel("Nombre del documento PDF");
		jtfNombrePDF = new JTextField(30);
		jtfNombrePDF.setText(strNombrePDF);
		jtfNombrePDF.setHorizontalAlignment (JTextField.CENTER);
		JPanel panNombrePDF = new JPanel(new FlowLayout(FlowLayout.CENTER));
      panNombrePDF.add(Box.createHorizontalStrut(15));
		panNombrePDF.add(lblNombrePDF);
		panNombrePDF.add(jtfNombrePDF);
		
		//Crear el boton nuevo
		JButton btnGenerarPDF = new JButton("Generar PDF");
		JPanel panGenerarPDF = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panGenerarPDF.add(btnGenerarPDF);

		//Todos los componentes estan en un Box Vertical
		//la clase Box se usa para alinear los controles
		Box boxVertical = Box.createVerticalBox();
		boxVertical.add(Box.createVerticalStrut(50));
		boxVertical.add(panTitulo);
		boxVertical.add(panNombrePDF);
		boxVertical.add(Box.createVerticalStrut(10));
		boxVertical.add(panGenerarPDF);

		//Agregar el Box a la ventana
		add(boxVertical);
		setResizable(false);	//No maximizar ni cambiar tamanio
		//Al dar en la X terminar todo el programa
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    	// ########### ESCUCHADOR BOTON NUEVO   ##########
    	ActionListener escuchadorGenerarPDF = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
        		strNombrePDF = jtfNombrePDF.getText();
            GenerarPDFEmpleados ejemplo = new GenerarPDFEmpleados(strTituloPDF,strNombrePDF);
       		//Preguntar al usuario si desea abrir el documento PDF
       		int respuesta = JOptionPane.showConfirmDialog(null,"Se ha generado el documento "+strNombrePDF+", ¿Desea abrirlo?","Pregunta",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);
       		//Si la respuesta es SI, abrirlo
				if(respuesta == JOptionPane.YES_OPTION)
					ejemplo.abrirPDF ();
          
        	}
   	};
    	btnGenerarPDF.addActionListener(escuchadorGenerarPDF);

    	
	}	//Fin del constructor

	//hace visible la ventana	
	public void mostrar()
	{
		setVisible(true);
	}

	public static void main(String[] args) 
   {
		JfrPrincipal ejemplo = new JfrPrincipal("Ventana principal de Usuario",400,400);
		ejemplo.mostrar();
   }
}

Y a continuacion una imagen de la GUI que se genera:

GUI para el ejemplo

GUI para el ejemplo

El primer Jlabel es un rotulo para la ventana, el segundo Jlabel es una etiqueta para el JTextField con la cual se le indica al usuario que debe escribir el nombre del documento PDF (con extension), el JTextField es el campo donde el uuario debe escribir el nombre del PDF. El JButton al darle click; el usuario generara el documento PDF de una tabla llamada Empleados e inmediatamente se le preguntara si desea abrirlo, aca una imagen:

Pregunta al usuario si desea abrir el PDF

Pregunta al usuario si desea abrir el PDF


Si el usuario da click en el boton Si del mensaje llama al metodo abrirPDF() de un objeto de la clase GenerarPDFEmpleados.java el cual abrira en una nueva ventana el documento PDF dentro del cual se muestra el contenido de la tabla empleados, aca una imagen del PDF:
PDF generado con datos de tabla empleados creada en MySQL

PDF generado con datos de tabla empleados creada en MySQL

GenerarPDFEmpleados.java
En esta clase es donde se hace uso de la libreria iText para generar un documento PDF. El codigo de esta clase es el siguiente:


//		Instituto Tecnologico de Zacatepec
//  	Descripcion:  Programa que genera un archivo PDF con datos de una base de datos
//		en mySQL y con ayuda de la libreria iText
//  	Author: Gonzalo Silverio   gonzasilve@hotmail.com
//		Archivo: GenerarPDFEmpleados.java

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

import com.lowagie.text.Anchor;
import com.lowagie.text.BadElementException;
import com.lowagie.text.Cell;
import com.lowagie.text.Chapter;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.List;
import com.lowagie.text.ListItem;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Section;
import com.lowagie.text.Table;
import com.lowagie.text.Element;
import com.lowagie.text.PageSize;

import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPTable;

import com.lowagie.text.Image;

import java.sql.*;

public class GenerarPDFEmpleados
{
	private String strNombreDelPDF;

	private  Font fuenteNegra10 = new Font(Font.TIMES_ROMAN, 10, Font.BOLD, Color.BLACK);
	private  Font fuente8 = new Font(Font.TIMES_ROMAN, 8, Font.NORMAL, Color.BLACK);
	private  Font fuenteAzul25 = new Font(Font.TIMES_ROMAN, 25, Font.BOLD, Color.BLUE);

	Color grisClaro = new Color( 230,230,230);	
	Color azulClaro = new Color( 124,195,255 );

	//############# VARIABLES PARA MANEJO DE BASE DE DATOS ########################
	//Guarda la consulta operacion a realizar
	String strConsultaSQL;
	//Apuntador a la conexion
	Connection conn = null;	
	//Para ejecutar operaciones SQL
	Statement estSQL1;
	//Para guardar los resultados de una operacion SELECT
	ResultSet rs;
	Document document;
	PdfWriter writer;
	String strRotuloPDF;
	
	//Metodo principal del ejemplo
	public GenerarPDFEmpleados(String titulo, String nomPDF)
	{
		strRotuloPDF = titulo;
		strNombreDelPDF = nomPDF;
		try 
		{		//Hoja tamanio carta, rotarla (cambiar a horizontal)
			document = new Document( PageSize.LETTER.rotate() );
			
			writer = PdfWriter.getInstance(
			// that listens to the document
					document,
					// direccionar el PDF-stream a un archivo
					new FileOutputStream(strNombreDelPDF));
			document.open();

			agregarMetaDatos(document);
			agregarContenido(document);
			
			document.close();
			
			System.out.println("Se ha generado el PDF: "+ strNombreDelPDF);
				
		} catch (Exception e) 
		{
			e.printStackTrace();
		}
	}
	
	//agrega el contenido del documento; para este ejemplo agrega una tabla con datos y una imagen
	//Espera como entrada el documento donde agregara el contenido
	private void agregarContenido(Document document) throws DocumentException
	{
		Paragraph ParrafoHoja = new Paragraph();
				
		// Agregamos una linea en blanco al principio del documento
		agregarLineasEnBlanco(ParrafoHoja, 1);
		// Colocar un encabezado (en mayusculas)
		ParrafoHoja.add(new Paragraph(strRotuloPDF.toUpperCase (), fuenteAzul25) );
		agregarLineasEnBlanco(ParrafoHoja, 1);
		// 1.- AGREGAMOS LA TABLA
		agregarTabla(ParrafoHoja);
		//Agregar 2 lineas en blanco
		agregarLineasEnBlanco(ParrafoHoja, 2);
		// 2.- AGREGAMOS LA IMAGEN
		try
		{
			Image im = Image.getInstance("logo_mysql.gif");
			im.setAlignment(Image.ALIGN_CENTER | Image.TEXTWRAP );
			im.setWidthPercentage (50);
	      ParrafoHoja.add(im);
		}
		catch(Exception e)
		{
			e.printStackTrace ();
		}
		
		document.add(ParrafoHoja);

	}

	//Se conecta al DBMS MySQL , obtiene los datos de la tabla (SELECT) y los acomoda en una tabla JTable de iText.
	// Espera como entrada el parrafo donde agregara la tabla
	private void agregarTabla(Paragraph parrafo) throws BadElementException 
	{
		//Anchos de las columnas
		float anchosFilas[] = { 0.2f,1f,1f,0.5f,0.5f,0.3f,1f,1.5f,0.7f };
		PdfPTable tabla = new PdfPTable(anchosFilas);
		String rotulosColumnas[] = {"id","Nombre","Apellidos","Sexo","Telefono","Edad","Correo","Direccion","Fecha\nContratacion"};
		// Porcentaje que ocupa a lo ancho de la pagina del PDF
		tabla.setWidthPercentage(100);
		//Alineacion horizontal centrada
		tabla.setHorizontalAlignment(Element.ALIGN_CENTER);
		//agregar celda que ocupa las 9 columnas de los rotulos
		PdfPCell cell = new PdfPCell(new Paragraph("Tabla: Empleados"));
		cell.setColspan(9);
		//Centrar contenido de celda
		cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		//Color de fondo de la celda
		cell.setBackgroundColor (azulClaro);		
		tabla.addCell(cell);

    	try
    	{
			if ( ConectarBD() )
			{
				// Mostrar los rotulos de las columnas
				for(int i=0; i<rotulosColumnas.length; i++)
				{
					cell = new PdfPCell(new Paragraph(rotulosColumnas[i],fuenteNegra10));
					cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
					cell.setHorizontalAlignment(Element.ALIGN_CENTER);
					cell.setBackgroundColor (grisClaro);
					tabla.addCell(cell);
				}
				
				//Consultar la tabla empleados
				strConsultaSQL = "SELECT * FROM empleados";
				//ejecutar consulta
				rs = estSQL1.executeQuery(strConsultaSQL);

				//Iterar Mientras haya una fila siguiente
	   		while (rs.next())
	   		{			//Agregar 9 celdas
					cell = new PdfPCell(new Paragraph(String.valueOf(rs.getInt ("idEmpleado")),fuente8 ));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("nombre"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("apellidos"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("sexo"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("telefono"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(String.valueOf(rs.getInt("edad")),fuente8) );
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("correo"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("direccion"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getDate("fechaContratacion").toString (),fuente8 ) );
					tabla.addCell(cell);
   			}
   			
	        	//Cerrar los objetos de manejo de BD
	        	CrearConexion.cerrar(rs);			//ResultSet
	        	CrearConexion.cerrar(estSQL1);	//Statement
	        	CrearConexion.cerrar(conn);		//Connection
			}		//Fin de if que comprueba si se pudo conectar
			
		}
		catch(Exception e) 
		{
	    	System.out.println("Excepcion al ejecutar CONSULTA!!!");
	    	//Mostrar la traza de la pila
	    	e.printStackTrace();
		}
		//Agregar la tabla con los datos al parrafo que nos llego como entrada
		parrafo.add(tabla);
	}  //Fin del metodo que crea la tabla

	//Agrega las lineas en blanco  especificadas a un parrafo especificado
	private static void agregarLineasEnBlanco(Paragraph parrafo, int nLineas) 
	{
		for (int i = 0; i < nLineas; i++) 
			parrafo.add(new Paragraph(" "));
	}
	
	//Agrega los metadatos del documento, los metadatos a asignar son
	//Titulo, Asunto, Palabras clave, Autor y el sw o org con el cual fue generado
	private static void agregarMetaDatos(Document document)
	{
		document.addTitle("Documento con datos de tabla MySQL");
		document.addSubject("Usando iText y MySQL");
		document.addKeywords("Java, PDF, iText");
		document.addAuthor("Gonzalo Silverio");
		document.addCreator("https://gonzasilve.wordpress.com");
	}

	//devuelve true en caso de que si se pudo conectar
	//devuelve false sino se logro conectar
	public boolean ConectarBD() throws Exception
	{
	    try
	    {		
	    		//Aqui se instancia a la otra clase --> CrearConexion.java	    		
	    		//y se le mandan en el constructor los datos de conexion
	     		CrearConexion con  = new CrearConexion("root","root","prueba");
	     		//Obtiene una referencia a la conexion abierta
	     		conn = con.getConnection();
	      	
	      	//Comprobar si hay una refencia valida
	      	if(conn!=null)
	      	{
					//Mostrar MSG al usuario de la conexion se ha establecido
					System.out.println("Conexion establecida");
	     			//Se prepara para ejecutar sentencias en la conexion recien abierta
	      		estSQL1 = conn.createStatement();
					return true;
	      	}
	      	else
	      		return false;
	      		
	  	 }
	    catch (SQLException e)
	    {
	    	
	      // the above drop statements will throw exceptions
	      // if the types and tables did not exist before. Just ingore it.
	      System.out.println("Error en la conexion!!!");
	      e.printStackTrace();
	      return false;
	    }
	    		
	}
	
	//Abre el documento PDF
	public void abrirPDF()
	{
  		/* Abrir el archivo PDF */
		try 
		{
			Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + strNombreDelPDF);
		}
		catch (IOException e) 
		{
			e.printStackTrace();
		}	
	}	
}

Como se observa en el metodo conectarBD() se hace una instancia de la clase CrearConexion.java y se le mandan en el constructor los datos con los que se conectara a MySQL.

Los datos que se usan para conectarse al DBMS son:
Usuario: root
Password: root
Base de datos: prueba
Tabla: empleados
Host: localhost

Y la estructura de la tabla empleados es:

Estructura de la tabla empleados usada en este ejemplo

Estructura de la tabla empleados usada en este ejemplo

CrearConexion.java
Este archivo tiene como funcion la apertura de una conexion al DBMS MySQL y devuelve la referencia a traves de su metodo getConnection(). En el constructor recibe los datos que seran usados por el JConnector, el codigo de este archivo es:

// 		Instituto Tecnologico de Zacatepec
 // Descripcion: Clase para manejo de base de datos de MySQL
 // Author Gonzalo Silverio    gonzasilve@hotmail.com
 // Archivo: CrearConexion.java


import java.sql.*;

public class CrearConexion 
{
	//Datos por default de la conexion
	static String strUsuario = "usr";
	static String strPassword = "pw";
	static String strBaseDatos ="bd";
	static String strHost = "localhost";
	
	//Constructor, le llegan los datos con los que se conectara al DBMS
	public CrearConexion(String usr,String pw, String bd)
	{
		strUsuario = usr;
		strPassword = pw;
		strBaseDatos =bd;
		try
		{
			Class.forName("com.mysql.jdbc.Driver");		
		} catch ( ClassNotFoundException e )
		{
			System.out.println("ERROR: Error al cargar la clase del Driver");		
		}
	}
	
	//Constructor, le llegan los datos con los que se conectara al DBMS
	// a dif. del otro constructor le llega tbn el host (servidor)
	public CrearConexion(String usr,String pw, String bd,String srvr)
	{
		strUsuario = usr;
		strPassword = pw;
		strBaseDatos =bd;
		strHost = srvr;
		try
		{
			//Cargar el driver
			Class.forName("com.mysql.jdbc.Driver");		
		} catch ( ClassNotFoundException e )
		{
			System.out.println("ERROR: Error al cargar la clase del Driver\n");
			e.printStackTrace();
		}
	}
	
	public static Connection getConnection() throws SQLException 
	{
		//a continuacion vamos a formar la cadena de conexion, pero...
		//OJO aca debes poner el nombre de la instancia de SQL Server que vas a usar
		String url = "jdbc:mysql://"+strHost+"/"+strBaseDatos;
		return DriverManager.getConnection(url,strUsuario,strPassword);
	}

	//Cierra objeto Resultset
	public static void cerrar(ResultSet rs)
	{	
		try
		{
			rs.close();
		} 
		catch(Exception ex)
		{}
	}
	
	//Cierra objeto Statement
	public static void cerrar(Statement st)
	{
		try
		{
			st.close();
		} 
		catch(Exception ex)
		{}
	}
	
	//Cierra objeto Connection
	public static void cerrar(Connection con)
	{	
		try
		{
			con.close();
		} 
		catch(Exception ex)
		{}
	}
}	//Fin de la clase

Como se puede ver esta clase es la misma que use en el ejemplo Acceso a Base de datos de SQL Server desde java (Jconnector).

Eso es todo, hasta pronto y espero comentarios al respecto. ya sabes si quieres los fuentes, basta con pedirlos dejando tu mail. Suerte, bye.

Servlet que muestra en el navegador contenido de tabla MySQL y realiza busquedas

Creo que el titulo de la entrada lo dice todo, pero bueeno; A continuacion quiero mostrar como se despliega en el navegador el contenido de una tabla de MySQL a travez de un Servlet. Ademas, este ejemplo muestra una manera muy sencilla de realizar la busqueda de un registro en particular en base al contenido de alguno de los campos de la tabla. Anteriormente mostre el clasico Hola Mundo en version Servlet y ahora quiero mostrar algo mas util que pueda servir para adaptarlo a algun proyecto.

y como mencione en la anterior entrada del Servlet del hola mundo, vuelvo a repetir …Aca en mi otro blog hice un sencillo manual sobre como se instala y se configura Apache Tomcat. Y otra cosa, sino sabes nada de Servlets te recomiendo leer algo introductorio respecto al tema, por que aqui solo muestro el codigo sin practicamente nada de teoria de Servlets pues doy por hecho que ya sabes algo basico sobre el tema.

Yo en mi caso tengo en mi lap:
Version de la JVM: jdk1.6.0_23
Version de Apache: tomcat-6.0.29
Kernel de ubuntu: 2.6.35-27 (10.10)
Arquitectura del equipo: x86
Ruta de instalacion de Apache tomcat: /usr/local/apache-tomcat-6.0.29

En este ejemplo el nombre de la BD a usar es agenda y el nombre de la tabla es contactos (como se ve en el codigo, metodo conectarBD() ). A continuacion muestro la estructura de la tabla contactos:

Estructura de la tabla contactos

Estructura de la tabla contactos

Bueno sin mas preambulos y por que en el codigo se explica casi todo a continuacion muestro el codigo del ejemplo:

/*
          Instituto Tecnologico de Zacatepec
Descripcion: Servlet que muestra muestra en el navegador el contenido de 
            una tabla MySQL y realiza busquedas de registros en la misma.
Author:      Gonzalo Silverio  gonzasilve@gmail.como
Archivo:     ListarContactos.java
Compilar con:  javac ListarContactos.java
*/

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

//Para manejo de BD
import java.sql.*;

public class ListarContactos extends HttpServlet
{
	private static Connection connBD = null;
	Statement estSQL;
	ResultSet rs;
	String estadoPagina =  "nada" ;	//no llega ningun parametro en la URL
	
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        response.setContentType("text/html");        
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Agenda gonzasilve</title>");        
        response.addHeader("Pragma","no-cache");
        out.println("</head>");
        out.println("<body>");
        out.println("<br> <h1 align='center'> gonzasilve's Directorio de contactos! </h1> <br><br> ");
        //Formulario que se llama a si mismo para realizar las busquedas
        out.println("<form action='http://localhost:8080/ListarContactos' method='GET'> ");
        //Los campos de busqueda se muestran en una tabla independiente
        out.println("<table align='center' width='40%' border='0' >  ");
        out.println("<tr>");
        out.println("<td> <b> Buscar un contacto </b> </td>");
        out.println("<td> <input type='text' size='30' maxlength='30' name='txt_buscado'>  </td> ");
        out.println("<td>");
        out.println("<select name='campos'> ");
        out.println("<option value='id'>ID</option> ");
        out.println("<option value='nombre' selected >Nombre</option> ");
        out.println("<option value='correo'>Correo</option> ");
        out.println("<option value='tel'>Telefono</option> ");
        out.println("</select> ");
        out.println(" <input type='hidden' name='sts' value='buscar'> ");
        out.println("</td>");
        out.println("<td>");
        out.println(" <input type='submit' name='buscar' value='Buscar'> ");
        out.println("</td>");
        out.println("</tr>");
        out.println(" </table> ");  //Fin de campos de busqueda
        out.println("</form> ");
        out.println("<center>");
        out.println(" <b> <FONT color=:#0033FF> ");
        
        try
        {     //Obtener el estado (status-->sts)
          estadoPagina =  request.getParameter("sts");
          if(estadoPagina == null)
            estadoPagina="nada";
          //En caso de que el usuario pulso en el boton buscar
          if( estadoPagina.equals("buscar" ) )
                out.println("El registro buscado, si es encontrado sera marcado con color rojo.");
        }
        catch( Exception exx )
        {
           exx.printStackTrace();
        }
        
        //Desplegar los datos del registro actual en el navegador
        out.println(" </FONT> </b> <br> </center> ");
        out.println("<br> ");
        out.println("<table align='center' width='90%' border='1' cellpadding='0' cellspacing='0'>  ");
        out.println("<tr> ");
        out.println("<td> ");
        out.println("<table width='100%' align='center' border='0' cellpadding='0' cellspacing='0'> ");
        out.println(" <tr bgcolor='#CCFF66' >");
        //Columnas de la tabla de la BD
        out.println("<td align='center width='3%' > <b> ID </b> </td>  ");
        out.println("<td align='left' width='25%' > <b> Nombre </b> </td> ");
        out.println("<td align='center' width='20%' > <b> Correo </b> </td>  ");
        out.println("<td align='center' width='12%'> <b> Telefono </b> </td>  ");
        out.println("<td align='center' > <b> Fotografia </b> </td>  ");
        out.println(" </tr>");
        int i=0, idContacto=0;
        String cmp_DondeBuscar,txt_Buscado;
        try
        {
        	conectarBD();
        	rs = estSQL.executeQuery("SELECT * FROM contactos");
	        while( rs.next() )    //Mientras haya una sig. tupla
	        {     // en caso de que el estado sea buscando
	        	if( estadoPagina.equals("buscar" ) )
	        	{
              //Obtener el campor x el que se va a buscar
	        		cmp_DondeBuscar = 	String.valueOf( request.getParameter("campos") );
              //Obtener el texto a buscar
	        		txt_Buscado		=	String.valueOf( request.getParameter("txt_buscado") ).toLowerCase();
                //Si se indico buscar x ID
	        		if( cmp_DondeBuscar.equals("id") )
	        		{
	        			idContacto = Integer.parseInt( txt_Buscado );
	        			if( idContacto == rs.getInt("id") )
		            		out.println(" <tr bgcolor='red'>");
	        		}   //Si se indico buscar x nombre
	        		else if( cmp_DondeBuscar.equals("nombre")  )
	        		{	        			
	        			if( txt_Buscado.equals( rs.getString("nombre").toLowerCase() ) )
		            		out.println(" <tr bgcolor='red'>");
	        		}     //Si se indico buscar x correo
	        		else if( cmp_DondeBuscar.equals("correo")  )
	        		{	        			
	        			if( txt_Buscado.equals( rs.getString("correo").toLowerCase() ) )
		            		out.println(" <tr bgcolor='red'>");
	        		}     //Si se indico buscar x telefono
	        		else if( cmp_DondeBuscar.equals("tel")  )
	        		{	        			
	        			if( txt_Buscado.equals( rs.getString("tel").toLowerCase() ) )
		            		out.println(" <tr bgcolor='red'>");
	        		}
	        		 
	        	}
	        	else
	        	{           //Para alternar entre dos colores diferentes de fila
		        	if( i%2==0 )
		            	out.println(" <tr bgcolor='#CCCCFF'>");
		            else
		            	out.println(" <tr bgcolor='#EEEEEE'>");
	        	}
              //Mostrar los datos del registro actual en el navegador
            out.println(" <td>"+ rs.getInt("id")+" </td>");
            out.println(" <td>"+ rs.getString("nombre")+"</td>");
            out.println(" <td>"+ rs.getString("correo")+"</td>");
            out.println(" <td>"+ rs.getString("tel")+"</td>");
            out.println(" <td>"+ rs.getString("fotografia")+"</td>");
            out.println(" </tr>");
            i++;
	        } //Fin de while que recorre tuplas
        	
        }
        catch( SQLException sqlex )
        {
        	out.println(" 3rror al conectar en la pagina principal");
        	sqlex.printStackTrace();
        }
       	
        out.println("</table>");
        out.println("</td> ");
        out.println("</tr> ");
        out.println("</table>");
        out.println("<br><br>");
        out.println("</body>");
        out.println("</html>");
    }
    
    //Conectar con MySQL y devuelve true solo en caso de que
    //Se haya obtenido una conexion a la BD especificada
    public boolean conectarBD() throws SQLException
    {
      	try
		{
      //seleccionar el driver
			Class.forName("com.mysql.jdbc.Driver");
      //especificar datos de conexion
			connBD = DriverManager.getConnection("jdbc:mysql://localhost/agenda","root","12345");
			estSQL = connBD.createStatement();
      //Verificar si se obtuvo la conexion correctamente
			if (connBD == null )
				return false;   //No se pudo conectar
			return true;
		}
		catch ( SQLException e )
		{
			System.out.println("ERROR: 3xcepcion al conectar la BD ");
			return false;
		}
		catch( Exception es )
		{
			System.out.println("ERROR: 3xcepcion al conectar la BD ");
			return false;
		}
    }
}

Como se observa la clase del Servlet se llama ListarContactos; no olvidar dar de alta a este Servlet en el archivo /usr/local/apache-tomcat-6.0.29/webapps/ROOT/WEB-INF/web.xml. Para dar de alta este servlet basta con agregar las siguientes lineas a dicho archivo:

	<!-- SERVLET QUE LISTA Y BUSCA REGISTROS DE UNA TABLA -->
	<servlet>
		<servlet-name>ListarContactos</servlet-name>
		<servlet-class>ListarContactos</servlet-class>
	</servlet>

	<!-- Standard Action Servlet Mapping -->
	<servlet-mapping>
		<servlet-name>ListarContactos</servlet-name>
		<url-pattern>/ListarContactos</url-pattern>
	</servlet-mapping>

Y a continuacion muestro un pantallazo de la compilacion de este Servlet en la consola:

Compilacion del Servlet que lista contactos de tabla MySQL

Compilacion del Servlet que lista contactos de tabla MySQL

Ahora el Servlet en ejecucion en el navegador Firefox (disfrazado un poco):

Servlet que lista registros de tabla contactos MySQL

Servlet que lista registros de tabla contactos MySQL

Pantallazo donde se esta buscando un registro:

Servlet mostrando un contacto encontrado

Servlet mostrando un contacto encontrado

Es todo, espero comentarios sobre dudas, sugerencias o criticas constructivas, ya sabes si quieres el .java basta con dejar tu mail. Hasta pronto y gracias por pasar por aqui. see you :p

Como guardar la ruta de un archivo en tabla MySQL y java

A veces en algun programa necesitamos guardar la ruta de un archivo. Por ejemplo si es un programa para llevar el control de empleados tal vez sera necesario guardar las fotografias de los empleados o una imagen de un producto, o la ruta de un archivo de documento, etc. Es por eso que se me ocurrio mostrar como se puede guardar la ruta de un archivo en una tabla de MySQL y recuperarla.

Parece facil, pero tiene su chiste, bueno para mostrar voi a diseñar una sencilla BD con una sola tabla que se llame productos con 3 unicos campos: el Id, el nombre del producto y su imagen (imagen muestra del producto). Los comandos SQL para crear la BD y la tabla son los siguientes:

CREATE DATABASE pruebaRuta;
USE pruebaRuta;
CREATE TABLE productos(id int auto_increment not null,nombre varchar(100), imagen varchar(2000), primary key(id) );

Observe que el id es auto_increment y por lo tanto el DBMS lo genera automaticamente, el campo imagen guarda una cadena que sera la ruta donde esta la imagen del producto.

Ahora imaginemos que las imagenes las tenemos almacenadas en la siguiente ruta del disco duro: c:\imagenes\productos. Podria pensarse que para realizar una insercion para registrar un nuevo producto en la tabla se haria con el comando:

INSERT INTO productos(nombre, imagen) VALUES('Chiles chipotles','c:\imagenes\productos\chipoles_100gr.jpg');

y de hecho si ese comando lo ejecutamos en la consola de MySQL nos dice que se inserto con exito:

 

insercion mal

insercion mal

bien, ahora hagamos un SELECT de la tabla para mostrar si se inserto…

 

select mal

select mal

…pero hooo! sorpresaa faltan las diagonales (slash). al parecer el DBMS las toma como secuencias de escape y las omite, no las guarda pues, desconozco sinceramente por que no guarda las diagonales pero e ideado una clase java que agrega doble diagonal o cualquier otro caracter para reemplazar los separadores de carpetas por unos que si son validos. La forma correcta de registrar un nuevo producto es esta:

INSERT INTO productos(nombre, imagen) VALUES('Chiles chipotles','c:\\imagenes\\productos\\chipoles_100gr.jpg');

ahora muestro como MySQL no manda error:

insert bien

insert bien

y ahora otra vez el SELECT y vemos como ahora si se guardo correctamente

 

select bien

select bien

aahh esta vez si se inserto bien la ruta del producto. Obviamente que las inserciones aqui hechas se han hecho desde la linea comandos del cliente de MySQL pero esta operaciones de INSERT se hacen mediante un programa java con una interfaz de usuario y esas cosas.
Para ilustrar todo esto con un ejemplo practico he creado 3 clases: JfrPrincipal.java, JfrAltaProductos.java, JfrVisorProductos.java, los cuales voi a ir explicando poco a poco a continuacion. No olvidar que el objetivo de este ejemplo es la de mostrar como mandar correctamente la ruta de un archivo a una tabla de MySQL y como recuperarla para mostrar el archivo (p. ej. imagenes, .txt) o abrirlo. A continuacion muestro el diagrama de clases del ejemplo:

Clases del ejemplo Corregir Ruta Archivo

Clases UML del ejemplo Corregir Ruta Archivo

Como se puede observar la clase que nos interesa la e resaltado en otro color, esta clase se instancia desde la clase JfrAltaProductos.java que es la que nos permite dar de alta a un nuevo producto, se llama desde aqui por que antes de dar de alta un producto (INSERT) se debe correguir la ruta.

JfrPrincipal.java
Este archivo es la clase principal y unicamente tiene la funcion de mostrar una GUI con dos botones para que el usuario elija abrir el visor de imagenes o agregue un nuevo producto. En el codigo hay algunos comentarios para describir brevemente que es lo que se hace:

/*
		Instituto Tecnologico de Zacatepec, Mor.
Descripcion:  Ventana principal del ejemplo, desde esta interfaz el usuario puede
					elegir entre ver las imagenes o dar de alta un nuevo producto.
Autor:  Gonzalo Silverio   gonzasilve@gmail.com
Archivo JfrPrincipal.java
*/

import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.event.*;

public class JfrPrincipal extends JFrame
{
	//Constructor
	JfrPrincipal(String titulo, int ancho, int alto)
	{
		//Establecer titulo, tamanio y posicion en la pantalla
		super(titulo);
		setSize(ancho,alto);
		setLocationRelativeTo(null);	//centrado
		//Rotulo principal de la ventana
		JLabel lblTitulo = new JLabel("Ventana principal");
		JPanel panTitulo = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panTitulo.add(lblTitulo);
		//Crear el boton nuevo
		JButton btnNuevo = new JButton("Nuevo");
		JPanel panNuevo = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panNuevo.add(btnNuevo);
		//Crear el boton para abrir el visor de imagenes
		JButton btnVisorImagenes = new JButton("Visor de imagenes");
		JPanel panVisor = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panVisor.add(btnVisorImagenes);
		
		//Todos los componentes estan en un Box Vertical
		//para alinear los controles
		Box boxVertical = Box.createVerticalBox();
		boxVertical.add(Box.createVerticalStrut(50));
		boxVertical.add(panTitulo);
		boxVertical.add(panNuevo);
		boxVertical.add(panVisor);
		//Agregar el Box a la ventana
		add(boxVertical);
		setResizable(false);	//No maximizar ni cambiar tamanio
		//Al dar en la X terminar todo el programa
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    	// ########### ESCUCHADOR BOTON NUEVO   ##########
    	ActionListener escuchadorAlta = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
            JfrAltaProductos ejemplo = new JfrAltaProductos("Alta de un nuevo producto",400,400);
            ejemplo.mostrar();
            //Ocultar la ventana principal
            setVisible(false);
        	}
   		};
    	btnNuevo.addActionListener(escuchadorAlta);

    	// ########### ESCUCHADOR PARA BOTON VISOR DE IMAGENES   ##########
    	ActionListener escuchadorVisor = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
            JfrVisorProductos ejemplo = new JfrVisorProductos("Visor de imagenes de productos",400,400);
            ejemplo.mostrar();
            //Ocultar la ventana principal
            setVisible(false);
        	}
   		};
    	btnVisorImagenes.addActionListener(escuchadorVisor);
    	
	}	//Fin del constructor

	//hace visible la ventana	
	public void mostrar()
	{
		setVisible(true);
	}

	public static void main(String[] args) 
   {
		JfrPrincipal ejemplo = new JfrPrincipal("Visor de Imagenes de productos",400,400);
		ejemplo.mostrar();
   }
}

Ahora muestro imagen de la ventana que genera el codigo anterior:

Ventana principal del ejemplo.

Ventana principal del ejemplo.

Como se puede ver es una interfaz muy sencilla y es el punto de entrada del programa.

JfrAltaProductos.java
Esta clase permite dar de alta un nuevo producto, es decir permite hacer un INSERT en la tabla de productos con el nombre del producto y la ruta que corresponde a una imagen previa de dicho producto. En el codigo se muestra los comentario correspondientes explicando el codigo:

/*
		Instituto Tecnologico de Zacatepec, Mor.
Descripcion:  Ventana para dar de alta a un nuevo producto, antes de dar de alta
			un producto se debe corregir la ruta del archivo de imagen del producto.
Autor:  	Gonzalo Silverio   gonzasilve@gmail.com
Archivo: JfrAltaProductos.java
*/

import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.Color;
import java.awt.event.*;
//Para usar la clase File con el FilesChooser
import java.io.*;
//Para usar operacion con BD (JDBC)
import java.sql.*;

public class JfrAltaProductos extends JFrame
{
	
	 //Script SQL para crear la tabla productos:
	 //CREATE TABLE productos(id int auto_increment not null,nombre varchar(100), imagen varchar(2000), primary key(id) );

   JTextArea jtaRutaImagen;
   JTextField jtfNombre;

	private static Connection con = null;
	Statement st;

	//Constructor
	JfrAltaProductos(String titulo, int ancho, int alto)
	{
		super(titulo);
		setSize(ancho,alto);
		setLocationRelativeTo(null);
		JLabel lblTitulo = new JLabel("Datos del producto");
		JPanel panTitulo = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panTitulo.add(lblTitulo);
		
		//Crear una etiqueta y su campo de texto correspondiente para capturar el
		//nombre del producto
		JLabel lblNombre = new JLabel("Nombre: ");
		jtfNombre = new JTextField(20);
		JPanel panNombre = new JPanel(new FlowLayout(FlowLayout.LEFT));
      panNombre.add(Box.createHorizontalStrut(15));
		panNombre.add(lblNombre);
		panNombre.add(jtfNombre);
		//Crear el boton examinar
		JButton btnExaminar = new JButton("Examinar...");
      btnExaminar.addActionListener(new seleccionarImagen());
		
		//Crear el area de texto para mostrar la ruta absoluta del archivo
      JPanel panRutaImagen = new JPanel(new FlowLayout(FlowLayout.LEFT));
         jtaRutaImagen = new JTextArea(4,20);
         jtaRutaImagen.setDisabledTextColor(Color.BLUE);
         jtaRutaImagen.setLineWrap(true);
         jtaRutaImagen.setEnabled(false);
         JScrollPane scrollRutaImagen = new JScrollPane(jtaRutaImagen);
         scrollRutaImagen.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
         scrollRutaImagen.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
      panRutaImagen.add(Box.createHorizontalStrut(15));
      panRutaImagen.add(scrollRutaImagen);
      panRutaImagen.add(btnExaminar);
		//Crear el boton Guardar
		JButton btnGuardar = new JButton("Guardar");
		JPanel panGuardar = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panGuardar.add(btnGuardar);
		//Crear el boton Cancelar
		JButton btnCancelar = new JButton("Cancelar");
		JPanel panCancelar = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panCancelar.add(btnCancelar);
		//Alinear los botones Guardar y Cancelar en forma horizontal
      Box boxGuardarCancelar = Box.createHorizontalBox();
      boxGuardarCancelar.add(btnGuardar);
      boxGuardarCancelar.add(Box.createHorizontalStrut(30));
      boxGuardarCancelar.add(btnCancelar);

		//Agregar todos los controles de usuario al Box Horizontal principal
		Box boxVertical = Box.createVerticalBox();
		boxVertical.add(Box.createVerticalStrut(50));
		boxVertical.add(panTitulo);
      boxVertical.add(Box.createVerticalStrut(50));
      boxVertical.add(panNombre);
      JPanel panEtiquetaRuta = new JPanel(new FlowLayout(FlowLayout.LEFT));
      panEtiquetaRuta.add(Box.createHorizontalStrut(15));
      panEtiquetaRuta.add(new JLabel("Imagen previa del producto"));
      boxVertical.add(panEtiquetaRuta);      
		boxVertical.add(panRutaImagen);
      boxVertical.add(Box.createVerticalStrut(10));
      boxVertical.add(boxGuardarCancelar);
      boxVertical.add(Box.createVerticalStrut(100));
		//Agregar el Box principal a este JFrame
		add(boxVertical);
		//No permitir maximizar ni redimensionar este JFrame
		setResizable(false);

// ##################### ESCUCHADOR DE VENTANA #############################################
    	//Para que al dar clic en la x de la esquina de este JFrame
      //se muestre por default la ventana principal
		this.addWindowListener(new WindowAdapter() 
		{
			public void windowClosing(WindowEvent e)
			{
            JfrPrincipal ejemplo = new JfrPrincipal("Visor de Imagenes de productos",400,400);
            ejemplo.mostrar();

				setVisible(false);
			}

			public void windowClosed(WindowEvent e)
			{
            JfrPrincipal ejemplo = new JfrPrincipal("Visor de Imagenes de productos",400,400);
            ejemplo.mostrar();
				setVisible(false);
			}
		});

    	// ########### ESCUCHADOR BOTON CANCELAR   ##########
    	ActionListener escuchadorCancelar = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
            JfrPrincipal ejemplo = new JfrPrincipal("Visor de Imagenes de productos",400,400);
            ejemplo.mostrar();
            setVisible(false);
        	}
   	};
    	btnCancelar.addActionListener(escuchadorCancelar);

    	// ########### ESCUCHADOR BOTON GUARDAR   ##########
    	ActionListener escuchadorGuardar = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
        		//Validar que NO haya campos vacios
            if(hayCamposVacios())
            {
            	JOptionPane.showMessageDialog(null,"Debes escribir el nombre y elegir la ruta de la imagen, hay campos vacios");
            	return;
            }

            if( conectarBaseDatos() )
            {
               if( altaProducto() )
               {
               	JOptionPane.showMessageDialog(null,"Producto guardado con exito");
               	jtfNombre.setText("");
               	jtaRutaImagen.setText("");
               }                  
               else
                  JOptionPane.showMessageDialog(null,"No se pudo guardar");
            }
            else
               JOptionPane.showMessageDialog(null,"No se pudo Conectar la BD");

        	}
   	};
    	btnGuardar.addActionListener(escuchadorGuardar);
    	
	}  	//Fin del costructor

	//Conecta la base de datos y se prepara para un sentencia SQL
	//Devuelve true solo si la conexion tuvo exito
   public boolean conectarBaseDatos()
   {
      try
      {
         Class.forName("com.mysql.jdbc.Driver");
         String strCadenaConexion = "jdbc:mysql://localhost/pruebaRuta";
         con = DriverManager.getConnection(strCadenaConexion,"root","12345");
         if (con == null )
            return false;
         
         //Preparar conexion para ejecutar una sentencia SQL
         st = con.createStatement();
         return true;
      }
      catch(SQLException sqlex)
      {
         sqlex.printStackTrace();
          return false;
      }
      catch(Exception e)
      {
         e.printStackTrace();
         return false;
      }
   }

	//Realiza un ALTA en la tabla de productos
   //devuelve true solo si se pudo realizar con exito el INSERT en la tabla
   public boolean altaProducto()
   {
      try
      {
         String strRutaImagen;
         //Instanciamos la clase que corrige la ruta del archivo
         CorregirRuta ruta1 = new CorregirRuta(jtaRutaImagen.getText(),"\\", "\\\\");
         //CORREGIR LA RUTA
         strRutaImagen = ruta1.obtenerRutaCorregidaWindows();
         //Hacer el insert con la ruta corregida
         int res = st.executeUpdate("INSERT INTO productos(nombre,imagen) VALUES('"+jtfNombre.getText()+"','"+strRutaImagen+"')");
         
         if(res==1)
            return true;
         else
            return false;

      }
      catch(SQLException sqlex)
      {
         sqlex.printStackTrace();
          return false;
      }
      catch(Exception e)
      {
         e.printStackTrace();
         return false;
      }
   }

   //Comprueba true si alguno de los 2 campos esta vacios
   public boolean hayCamposVacios()
   {
      if( jtfNombre.getText().isEmpty() || jtaRutaImagen.getText().isEmpty() )
         return true;
      return false;
   }

   //hace visible la ventana
	public void mostrar()
	{
		setVisible(true);
	}

	//Clase interna
	class seleccionarImagen implements ActionListener
	{
	  public void actionPerformed(ActionEvent ae)
	  {
	   String strSeleccionado;
	   JFileChooser jfcSeleccionarArchivo = new JFileChooser();
	   //Asignar el filtro para que solo se vean imagenes en la ventana abrir
	   jfcSeleccionarArchivo.addChoosableFileFilter(new FiltroImagenes());
	   //Filtro a usarse por defecto
	   jfcSeleccionarArchivo.setFileFilter(jfcSeleccionarArchivo.getChoosableFileFilters()[1]);
	
	      // Abre el cuadro de dialogo Abrir
	      int retval = jfcSeleccionarArchivo.showOpenDialog(JfrAltaProductos.this);
	      if (retval == JFileChooser.APPROVE_OPTION)
	      {
	          //... Si el usuario selecciono un archivo, entonces usarlo
	          File filSeleccionado = jfcSeleccionarArchivo.getSelectedFile();
	          //Obtener ruta absoluta del archivo seleccionado
	          strSeleccionado = filSeleccionado.getAbsolutePath();
	          //Mostrar la ruta al usuario en el area de texto correspondiente
	          jtaRutaImagen.setText(strSeleccionado);
	      }
	  }
	}		//fin de clase interna


}		//Fin de la clase

A continuacion muestro una imagen de la ventana que se genera:

Ventana para dar de Alta un producto.

Ventana para dar de Alta un producto.


Dejando campos vacios…
Mensaje de error al dejar Campos vacios en alta de producto.

Mensaje de error al dejar Campos vacios en alta de producto.

Como se observa e insertado un producto de ejemplo para ilustrar como funciona la ventana. El usuario una vez que escribe el nombre y elije un archivo de imagen (con el Boton Examinar…) debe dar clic en el Boton Guardar; al hacer esto el programa realiza una pequeña validacion de campos vacios y si se logra satisfacer se hace el INSERT. Una vez que se realizo el INSERT el programa limpia los campos para que el usuario siga dando de alta mas productos. Si el usuario ya termino debe dar click en el Boton Cancelar para volver a la ventana principal del ejemplo.

Como se puede observar en el metodo altaProducto() se instancia a la clase CorregirRuta.java (pasandole la ruta sin corregir) y se ejecuta su metodo obtenerRutaCorregidaWindows() para obtener la ruta corregida, tambien en la clase interna seleccionarImagen se hace una instancia de la clase FiltroImagenes.java, a continuacion muestro el codigo de dichas clases:

CorregirRuta.java
Permite corregir al ruta de carpetas de un archivo para poder almacenarla correctamente en una tabla de MySQL. Creo que no necesita mucha explicacion pues en el cabezado del archivo se describe, sin tanto rodeo, el codigo es…

/*
 *		Instituto Tecnologico de Zacatepec, Mor.
 * Descripcion:
 *	Clase que eecibe una ruta de archivo y una cadena que es con la que vienen separadas los nombres de las carpetas
 *  y otra cadena mas que es el nuevo separador con el que se van a separar ahora las carpetas.
 *  Devuelve la ruta ya corregida con el nuevo separador
 * @author: Gonzalo Silverio gonzasilve@gmail.com
 * Archivo: CorregirRuta.java
 * 
 */
import java.util.StringTokenizer;

public class CorregirRuta 
{
    String ruta, separador, nuevoSeparador;	

    public CorregirRuta(String laruta, String sep, String nuevoSep)
    {
    	ruta=laruta;
    	separador=sep;
    	nuevoSeparador=nuevoSep;
    }

    public String obtenerRutaCorregidaWindows()
    {
         StringTokenizer tokens=new StringTokenizer(ruta, separador);
         //Para guardar la ruta corregida
         String rutaCorregida = new String();
         //Contar los tokens (en este caso las carpetas, contado tambien
         // el nombre del archivo seleccionado).
         int noTokens = tokens.countTokens();
         int i = 1;
         do
         {		//Agregar el nuevo separador
            rutaCorregida += tokens.nextToken()+nuevoSeparador;
            i++;
         }while(i<noTokens);
         //Agregar a la ruta corregida el ultimo token, (nombre del archivo)
         rutaCorregida += tokens.nextToken();		
         //Mostrar la ruta corregida en la consola
         System.out.println(rutaCorregida+"\n"+noTokens+ " tokens");
         return rutaCorregida;
    }
}

FiltroImagenes.java
Clase para filtrar unicamente los archivos de imagenes con extension .jpeg , .jpg , .png , .gif en la ventana de dialogo estandar Abrir.

/*
		Instituto Tecnologico de Zacatepec, Mor.
Descripcion:
   Clase que permite mostrar unicamente los ficheros .jpeg,  .jpg,  .gif en los cuadros de dialogo.
   Un filtro es un objeto de la clase FileFilter del paquete javax.swing.filechooser.. FileFilter es una
   clase obstracta con dos metodos abstractos accept y getDescription.
Author:  Gonzalo Silverio   gonzasilve@gmail.com
Archivo FiltroImagenes.java
*/

import javax.swing.filechooser.FileFilter;
import java.io.File;

public class FiltroImagenes extends FileFilter
{
    public boolean accept(File f)
   {
      if( f.isDirectory() )      
         return true;
      
      String nombreArchivo = f.getName().toLowerCase();
      if( nombreArchivo != null )
         if( nombreArchivo.endsWith(".jpeg") ||
            nombreArchivo.endsWith(".jpg")  ||
			nombreArchivo.endsWith(".png")  ||
            nombreArchivo.endsWith(".gif")
           )
            return true;
      
      return false;    
   }
   
   //Descripcion del filtro (se mostrara en la ventana abrir)
   public String getDescription()
   {
      return "Archivos de imagenes ( *.jpg ,  *.png ,  *.gif )";
   }
}        //Fin de la clase

JfrVisorProductos.java
Esta clase crea una ventana muy sencilla para mostrar los datos del producto, principalmente permite leer la ruta almacenada del archivo de imagen muestra del producto. En el codigo he comentado las partes mas importantes…

/*
		Instituto Tecnologico de Zacatepec, Mor.
Descripcion:  Ventana para mostrar las imagenes de los productos.
Autor:  Gonzalo Silverio   gonzasilve@gmail.com
Archivo: JfrVisorProductos.java
*/

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import java.sql.*;

public class JfrVisorProductos extends JFrame
{
   JPanel panelPrincipal, panelSuperior,panelInferior;

	private static Connection con = null;
	Statement st;
	ResultSet rs;
	
	int idsProductos[];    //Contiene los ID de los productos
	//Apunta al registro que se esta mostrando actualmente
	//Po defecto apuntar antes del primero
	int regActual = -1;
	int totalRegistros = 0;         //Contiene el total de registros que hay en la tabla
   JLabel lblNombreProducto = new JLabel("Nombre imagen");
   JPanel panImagen;
   JLabel lblImagen;
	Icon imagenn;
   
	JButton btnAnterior = new JButton("Anterior");
	JButton btnSiguiente  = new JButton("Siguiente");;
      
	Box boxpanSuperior;

   JfrVisorProductos(String tituloVentana, int ancho, int alto)
   {
      //Establecer titulo,tamanio, si es redimensionable y la posicion
      // de la ventana
      setTitle(tituloVentana);
      setSize(ancho,alto);
      this.setResizable(false);
      setLocationRelativeTo(null);
      
      JPanel panNombreProducto = new JPanel(new FlowLayout(FlowLayout.CENTER));
      panNombreProducto.add(lblNombreProducto);
      
      panelPrincipal = new JPanel(new BorderLayout());
      panelSuperior = new JPanel(new BorderLayout());
      panelInferior = new JPanel(new BorderLayout());
      btnAnterior.setMnemonic(KeyEvent.VK_A);
      btnSiguiente.setMnemonic(KeyEvent.VK_S);
      imagenn = new ImageIcon();
      lblImagen = new JLabel(imagenn);

      panImagen = new JPanel(new FlowLayout(FlowLayout.CENTER));
      panImagen.add(new JScrollPane(lblImagen), BorderLayout.CENTER);
      
      panelSuperior.add(panImagen);
      boxpanSuperior = Box.createVerticalBox();      
      boxpanSuperior.add(panNombreProducto);
      boxpanSuperior.add(panelSuperior);
      
      panelInferior.add(btnAnterior, BorderLayout.WEST);
      panelInferior.add(btnSiguiente, BorderLayout.EAST);
      panelPrincipal.add(boxpanSuperior, BorderLayout.CENTER);
      panelPrincipal.add(panelInferior, BorderLayout.SOUTH);

      add(panelPrincipal);
      inicializar();		//Cargar los IDs
      siguiente();		//Moverse al primer registro (estabamos uno antes del primero)
      
// ##################### ESCUCHADOR DE VENTANA #############################################
    	//Para que al dar clic en la x de la esquina de este JFrame
      //se muestre por default la ventana principal
	this.addWindowListener(new WindowAdapter() {

			public void windowClosing(WindowEvent e)
			{
            JfrPrincipal ejemplo = new JfrPrincipal("Visor de Imagenes de productos",400,400);
            ejemplo.mostrar();

				setVisible(false);
			}

			public void windowClosed(WindowEvent e)
			{
            JfrPrincipal ejemplo = new JfrPrincipal("Visor de Imagenes de productos",400,400);
            ejemplo.mostrar();
				setVisible(false);
			}
		});

    	// ########### ESCUCHADOR BOTON ANTERIOR   ##########
    	ActionListener escuchadorAnterior = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
				anterior();				//Va al anterior registro de la tabla
        	}
   		};
    	btnAnterior.addActionListener(escuchadorAnterior);

    	// ########### ESCUCHADOR BOTON SIGUIENTE   ##########
    	ActionListener escuchadorSiguiente = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
				siguiente();				//Va al siguiente registro de la tabla
        	}
   		};
    	btnSiguiente.addActionListener(escuchadorSiguiente);
    	
   }		//Fin del constructor

    //Inicializa el arreglo de IDs para que se puedan recorrer los registros 
    //y actualiza la variable que contiene el total de registros que hay en la tabla
    public void inicializar()
    {
        try
        {
            conectarBaseDatos();		//Nos conectamos con la BD
            rs = st.executeQuery("SELECT * FROM productos"); //seleccionamos todos los de la tabla productos

            //A continuacion se van a guardar en un arreglo los IDs de todos los productos
            if(! rs.first() )             //Nos movemos al primer registro
            	JOptionPane.showMessageDialog(null,"La tabla de productos esta vacia.");
	
            int contador = 0 ;
            do
                contador ++ ;           //Contar cuantos registros hay en la tabla productos
            while(rs.next());
            totalRegistros = contador-1;      //Guarda el numero de registros que hay en la tabla

            idsProductos = new int[contador];            //Crea el arreglo de IDs
            contador = 0;       //Reinicializar el contador
            rs.first();             //Nos movemos al primer registro
            do
                idsProductos[contador++]= rs.getInt("id");
            while(rs.next());

        }
        catch( SQLException sqlex  )
        {
            JOptionPane.showMessageDialog(null,"Error al inicializar el arreglo de IDs");
        }

    }		//Fin del metodo
    
    //permite desplazarse al anterior registro de la tabla
    public void anterior()
    {       
        regActual = regActual - 1;
        if ( regActual < 0 )
            regActual = 0;

        if(!consultarID())
            JOptionPane.showMessageDialog(null,"Error al ir al registro Anterior");
    }
	
	//permite desplazarse al siguiente registro de la tabla
    public void siguiente()
    {
        regActual = regActual + 1;
        if ( regActual > totalRegistros )
            regActual = totalRegistros;

        if(!consultarID())
            JOptionPane.showMessageDialog(null,"Error al ir al siguiente registro");
    }

    
    //Realiza una consulta con el ID seleccionado en regActual en el arreglo idsProductos[], 
    //devuelve true si se realizo la consulta con exito, en caso contrario devuelve false
    private boolean consultarID()
    {
        try
        {
            rs = st.executeQuery("SELECT * FROM productos where id="+idsProductos[regActual] ); //seleccionamos todos los de la tabla productos
            rs.first();                 //moverse al primer registro
            poblarCampos();
            return true;                //Todo se ejecuto con exito
        }
        catch(SQLException sqlex)
        {
            return false;
        }
    }		//Fin del metodo
    
    //rellena los campos con los datos del registro apuntado actualmente
    private void poblarCampos()
    {
        try
        {            
            lblNombreProducto.setText(rs.getString("nombre"));
            panImagen.remove(lblImagen);	//Borrar la imagen anterior
            //Recuperar de la BD la ruta del archivo de imagen
            imagenn = new ImageIcon(rs.getString("imagen"));	
            lblImagen = new JLabel(imagenn); //Cargar nueva imagen
            panImagen.add(lblImagen);	
            validate();
            repaint();	
				//Mostrar en la barra de titulo el reg. actual y el total
				setTitle("Visor de imagenes [producto "+(regActual+1)+" de "+(totalRegistros+1)+"]");

        }
        catch( SQLException sqlex  )
        {
            JOptionPane.showMessageDialog(null,"Error al rellenar los campos");
        }        
    }		//Fin del metodo
    

	//Conecta la base de datos y se prepara para un sentencia SQL
	//Devuelve true solo si la conexion tuvo exito
   public boolean conectarBaseDatos()
   {
      try
      {
         Class.forName("com.mysql.jdbc.Driver");
         String strCadenaConexion = "jdbc:mysql://localhost/pruebaRuta";
         con = DriverManager.getConnection(strCadenaConexion,"root","12345");
         if (con == null )
            return false;
         
         st = con.createStatement();
         return true;
      }
      catch(SQLException sqlex)
      {
         sqlex.printStackTrace();
          return false;
      }
      catch(Exception e)
      {
         e.printStackTrace();
         return false;
      }
   }		//Fin del metodo
   
	//hacer visible la ventana
	public void mostrar()
	{
		setVisible(true);
	}

}	//Fin de la clase

El aspecto de la ventana que se genera es esta:

Visor de imagenes de productos

Visor de imagenes de productos



Como se puede observar en el codigo e ideado una manera de recorrrer los registros de la tabla con dos botones, me parece interesante esto; lo mas probable es que en otra entrada del blog publique algo al respecto pero ya con los 4 botones de navegacion de registros (Primero,Anterior,Siguiente,Ultimo).

Nota: La marca Sabritas, Rufles y Coca-Cola son marcas registradas y solo las e puesto aqui con propositos educativos, si el autor(es) desea que la retire basta con pedirlo.

Bueno esto creo que se alargo demasiado, el objetivo era corregir la ruta y meti varias cosas mas, jajaja pero estoy seguro que aprendi mas y espero que tu tambien. Si estas leyendo esto es por que me imagino que leiste todo lo anterior. Ya sabes si tienes dudas puedes dejar un comentario, o si quieres los .java basta con dejar tu mail… hasta pronto y gracias por pasar por aqui ;).

Como hacer un INSERT y un SELECT en una BD de MySQL usando PHP

Desde hace ya tiempo tenia ganas de exponer algo sobre PHP pero hasta hoy me di a la tarea de invertir algo de tiempo en hacerlo. Y es que muchos dicen que ya PHP esta cayendo en desuso y otros que esta todavia muy fuerte, que esto y que el otro, la verdad es que no e investigado estadisticas para dar mi propia opinion. Pero creo que es un buen lenguaje web y cualquier estudiante de sistemas deberia tener a la mano algun apunte aunque sea algo basico, por eso me decidi a exponer algo.

En este ejemplo doy por hecho que ya tienes un servidor Apache correctamente instalado y configurado para cargar como modulo al PHP, sino sabes que es eso o todavia no lo tienes pues seria bueno irte ahora mismo a otro sitio y leer algo previo, por que sino no vas a entender mucho.

El ejemplo es muy sencillo; simplemente se realiza una insercion (INSERT) en una tabla que se llama usuarios, la tabla usuarios solamente tiene 3 campos y esta dentro de una Base de datos (BD) que lleva por nombre prueba.

Aca el comando SQL para crear la BD prueba y la tabla usuarios:

create database prueba;
create table usuarios(nick char(60) not null, pw char(40), correo char(255), primary key(nick));

Aca una imagen muestra en forma grafica el aspecto de la tabla ( creada con el workbench ):

Tabla usuarios

El ejemplo consta de tres archivos de codigo fuente; los cuales se describen a continuacion:

formularioAlta.html

Este archivo genera un formulario con tres campos de texto donde el usuario ingresara los datos que desea insertar en la tabla usuarios, una vez que el usuario a escrito los datos debe dar click en el boton Dar de alta! el cual es un boton submit que manda a llamar al archivo guardarAlta.php , dicho archivo es el que realmente guarda los datos en la tabla. Aca el codigo fuente:

<!--
                   Instituto Tecnologico de Zacatepec, Morelos
Descripcion:    Archivo fuente HTML que crea un formulario para capturar datos que seran
                enviados a un archivo .php para insertarlos en una BD de MySQL.
Author:         Gonzalo Silverio  gonzasilve@gmail.com
Fecha:          02/09/2010
Archivo:        formularioAlta.html
-->
<HTML>
   <HEAD>
        <TITLE>PHP y MySQL -Capturar datos alta</TITLE>
   </HEAD>

   <BODY>
      <FORM method="POST" action = "guardarAlta.php">
        Su nombre de usuario: <INPUT TYPE="text" name="nick" id="nick"><BR>
        Su Contraseña: <INPUT TYPE="password" name="password" id="password"><BR>
        Su correo electronico: <INPUT type="text" name="correo" id="correo"><BR><BR>
        <INPUT type="submit" NAME="enviar" VALUE="Dar de alta!" id="enviar">
      </FORM>
   </BODY>
</HTML>

guardarAlta.php
Este archivo abre una conexion con el servidor MySQL, captura los datos que llegan por el metodo POST, realiza dos comprobaciones para validar los datos a insertar, si los datos logran pasar satisfactoriamente las dos validaciones se hace la insercion y se avisa al usuario del exito de la operacion. A continuacion el codigo fuente, los comentarios indican donde se realiza cada cosa:

<!--
                   Instituto Tecnologico de Zacatepec, Morelos
Descripcion:    Archivo fuente de PHP que muestra como realizar una operacion INSERT
                en una BD de MySQL, con datos que llegan de un formulario HTML.
Author:         Gonzalo Silverio  gonzasilve@gmail.com
Fecha:          02/09/2010
Archivo:        guardarAlta.php
-->

<HTML>
<HEAD>
     <TITLE>PHP y MySQL -Resultados de alta</TITLE>
</HEAD>

<BODY>

<?php
   //Abrir una conexion con el servidor MySQL
   $conexio = mysql_connect("localhost","root","12345");
   mysql_select_db ("prueba", $conexio) OR die ("No se puede conectar");

   //Recoger datos que llegan
   $nik=$_POST['nick'];
   $pas=$_POST['password'];
   $cor=$_POST['correo'];

   //1.- Comprobar que no haya otro usuario con el mismo nick
   $sql="SELECT nick FROM usuarios WHERE nick='".$nik."'";
   $result=mysql_query($sql,$conexio);
   if($row=mysql_fetch_array($result))
   {
     echo "El nick <b>".$nik."</b> ya fue elegido por otro usuario.";
     exit();   /*cancelar la ejecucion del script y por tanto de la pagina web*/
   }
   //2.- Comprobar que no haya otro usuario registrado con el mismo correo
   $sql="SELECT correo FROM usuarios WHERE correo='".$cor."'";
   $result=mysql_query($sql,$conexio);
   if($row=mysql_fetch_array($result))
   {
     echo "El correo electronico <b>".$cor."</b> ya fue registrado por otro usuario.";
     exit();  /*cancelar la ejecucion del script y por tanto de la pagina web*/
   }
   //Si se ha logrado pasar las dos validaciones anteriores, entonces...
   //Realizar el INSERT en la tabla
   mysql_query("INSERT INTO usuarios(nick,pw,correo) VALUE ('$nik', '$pas', '$cor')",$conexio);
   echo "Registro Exitoso! <br><br> Usuario: <b>".$nik."</b> <br>Mail: <b>".$cor."</b>";

   //Cerrar la conexion
   mysql_close($conexio);
?>
 <BR><BR>
 <form method="POST" action="mostrarRegistros.php">
       <input type="submit" name="enviar" id="enviar" value="Ver registros de tabla">
 </form>
</BODY>
</HTML>

mostrarRegistros.php
Este archivo de codigo fuente abre una conexion con el servidor MySQL, realiza una seleccion (SELECT) de todos los registros de la tabla usuarios y los muestra en una tabla de tres columnas (3 campos tiene la tabla). A continuacion el codigo, otra vez los comentarios indican donde se realiza cada cosa:

<!--
                   Instituto Tecnologico de Zacatepec, Morelos
Descripcion:    Archivo fuente de PHP que muestra como realizar una operacion SELECT
                en una BD de MySQL.
Author:         Gonzalo Silverio  gonzasilve@gmail.com
Fecha:          02/09/2010
Archivo:        mostrarRegistros.php
-->
<HTML>
<HEAD>
     <TITLE>PHP y MySQL -Mostrar datos</TITLE>
</HEAD>

<BODY>

<?php
   //Abrir una conexion con el servidor MySQL
   $conexio = mysql_connect("localhost","root","12345");
   mysql_select_db ("prueba", $conexio) OR die ("No se puede conectar");

   //Seleccionar todos los registros
   $sql="SELECT * FROM usuarios";
   $result=mysql_query($sql,$conexio);

   //Mostrar los registros en una tabla en el navegador
   echo "<TABLE BORDER='1' width=50% align=center>";
   echo "<TR align=center><TD><b>Nick</b></TD><TD><b>Password</bd></TD><td><b>correo</b></td></TR>";
   while ($row=mysql_fetch_array($result))
   {
     echo "<TR><TD>".$row["nick"]."</TD><TD>".$row["pw"]."</TD><td>".$row["correo"]."</td></TR>";
   }
   echo "</TABLE>";

   //Cerrar la conexion
    mysql_close($conexio);

?>
<center>
   <br>
    <form method="POST" action="formularioAlta.html">
          <input type="submit" name="nuevo" id="enviar" value="Nuevo contacto">
    </form>
</center>
</BODY>
</HTML>

En resumen la logica del ejemplo es: El usuario abre el archivo formularioAltas.html en un navegador –> el usuario ingresa los datos y da clic en el boton submit –> Los datos son enviados al archivo guardarAlta.php –> Una vez que llegan los datos, se insertan en la BD (ho se muestra un msg de error de validacion) –> El usuario da clic en el boton Ver registros el cual es un boton submit y manda a llamar al archivo mostrarRegistros.php–> El archivo mostrarRegistros.php muestra los datos en el navegador.

A continuacion unos pantallazos de la ejecucion del ejemplo:

El usuario captura los datos y da clic en el boton Dar de alta!

formularioAltas.html

Se muestran al usuario resultados de la insercion, el usuario debe dar clic en el boton Ver registros de tabla

guardarAltas.php

Se muestran los datos en el navegador

mostrarRegistros.php Hasta pronto, comenta en caso de cualquier duda.

A %d blogueros les gusta esto: