jueves, 28 de febrero de 2008

Accediendo a SQLServer2005 Express con JDBC - Parte 2 Configuraciones en Netbeans y creación de una clase ConnectionFactory para acceso a base de dato

En esta segunda entrega veremos en primer lugar la implementación de una clase que nos permitirá manejar las operaciones de conexiíon con SQL Server 2005 ( y con otras más):

package sqlserver2005;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


public class ConnectionFactory {
public final static int TYPE_MSSQL = 10;
public final static int TYPE_MYSQL = 20;
public final static int TYPE_ORACLE_10G_EX = 30;
public final static int TYPE_MSSQL2005 = 40;
private String driver;
private String url;

/**
* Constructor que carga el driver jdbc para poder trabajar con la base de datos
*
* @param typeDBMS tipo de base de datos a utilizar
* @param hostName IP o nombre del servidor de base de datos
* @param databaseName nombre de la base de datos con la que deseamos trabajar
*/
public ConnectionFactory( int typeDBMS, String hostName, String databaseName ) {
switch( typeDBMS ){
case 10:{ // Para SQL Server 2000
driver = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
url = "jdbc:microsoft:sqlserver://" + hostName + ":1433;DatabaseName=" +
databaseName;
break;
}
case 20:{ // Para MySQL 5.0
driver = "com.mysql.jdbc.Driver";
url = "jdbc:mysql://" + hostName + ":3306/" +
databaseName;
break;
}
case 30:{ // Para en Oracle 10g Express Edition
if( databaseName.equals( "" ) )
databaseName = "XE";
else
databaseName = "XE";
driver = "oracle.jdbc.driver.OracleDriver";
url = "jdbc:oracle:thin:@//" + hostName + ":1521/" + databaseName;
break;
}
case 40:{ // Para SQL Server 2005 Express Edition
driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
url = "jdbc:sqlserver://" + hostName + ":1433;DatabaseName=" +
databaseName;
break;
}
}
try{
// cargar la clase Driver
Class.forName( driver );
}catch( ClassNotFoundException cnfe ){
System.out.println( "Error: exception loading driver class" );
}
}

/**
* Devuelve un objeto de tipo Connection válido
*
* @param user usuario de la base de datos
* @param password clave del usuario de la base de datos
* @return Connection
*/
public Connection getConnection( String user, String password ) throws SQLException
{
return DriverManager.getConnection( url, user, password );
}// fin del metodo getConnection

/**
* Metodo para liberar recursos de memoria, cerrando la conextion con la base
* de datos
*
* @param con parametro de tipo Connection
*/
public static void close( Connection con ){
try{
con.close();
}catch( SQLException sqle ){
showMessageError( sqle );
}
}// fin del método closeConnection

/**
* Cierra un objeto ResultSet (Registros)
* @param con parametro de tipo ResultSet
*/
public static void close( ResultSet rs ){
try{
rs.close();
}catch( SQLException sqle ){
showMessageError( sqle );
}
}// fin del método closeConnection


/**
* Cierra un objeto Statement (Consulta)
* @param con parametro de tipo Statement
*/
public static void close( Statement stmt ){
try{
stmt.close();
}catch( SQLException sqle ){
showMessageError( sqle );
}
}// fin del método close

/**
* Cierra un objeto Statement (Consulta)
* @param con parametro de tipo Statement
*/
public static void close( PreparedStatement ps ){
try{
ps.close();
}catch( SQLException sqle ){
showMessageError( sqle );
}
}// fin del método close

/**
* Cierra un objeto Statement (Consulta)
* @param con parametro de tipo Statement
*/
public static void close( CallableStatement cs ){
try{
cs.close();
}catch( SQLException sqle ){
showMessageError( sqle );
}
}// fin del método close

/** muestra un mensaje de error en consolo, según sea el caso */
private static void showMessageError( SQLException sqle ){
System.out.println( "Error:" +
"\nmensaje: " + sqle.getMessage() +
"\nSQLState: " + sqle.getSQLState() +
"\nVencorCode: " + sqle.getErrorCode() + "\n" );
}// fin del método showMessageError
}


martes, 26 de febrero de 2008

Accediendo a SQLServer2005 Express con JDBC - Parte 1 Configuracion de SQL Server 2005 Express

Introduccion
En este tutorial veremos como conectarnos y mostrar datos de SQL Server 2005 Express con JDBC.

Todo esta dividido en 4 partes:

  1. Configuracion de SQL Server 2005 Express
  2. Configuraciones en Netbeans y creación de una clase ConnectionFactory para acceso a base de datos.
  3. Operaciones SQL
  4. Posibles problemas
Requerimientos:
  1. Microsoft SQL Server JDBC Driver
    La última version, visite Microsoft SQL Server 2005 JDBC Driver.
  2. NetBeans con JRE (Java Runtime Environment) version 1.5 o superior
    Puede encontrar en NetBeans.org.
Configuración paso a paso:
  • SQL Server 2005 Express
Por defecto SQL Server 2005 no permite conexiones remotas y esta deshabilitado ls cuenta sa, asi que nosotros tenemos que hacer los cambios respectivos de forma manual, si usted trata de conectarse se le mostrará un mensaje de error por ejemplo sea cual sea el nombre de su servidor:







Otro problema por defecto que puede surgir cuando queremos conectarnos es que las conexiones TCP/IP están deshabilidatas en SQL Server 2005 Express. Asi que JDBC no se puede conectar y usted puede recibir la siguiente exception …
     Network error IOException: Connection refused: connec

Ahora vamos a configurar estas dos opciones:

1. Habilitar TCP/IP
  1. Click Inicio > Todos los programas > Microsoft SQL Server 2005 > Herramientas de configuracion > SQL Server Configuration Manager.
  2. En el panel izquierdo de la ventana d e SQL Server Configuration Manager, expandir Configuracion de red de SQL Server 2005 y click en Protocolos de SQLEXPRESS.
  3. En el panel derecho de la ventana de SQL Server Configuration Manager,Click derecho en TCP/IP y click para habilit ar.
  4. O través click derecho en TCP/IP y c lick en propiedades.
  5. En la ventana de propiedades deTCP/IP, click en el panel direcciones ip, y expanda IPALL.
  6. Debajo de IPALL, borrar el campo de TCP Dynamic Ports y entonces ingrese un numero de puerto en el campo TCP Port. Usualmente, tiene el valor por defecto de 1433.
  7. En la ventana de propiedades TCP/IP, click OK.
  8. En el panel izquierdo de la ventana SQL Server Configuration Manager, click en Servicios de SQL Server 2005.
  9. En el panel derecho de la ventana de SQL Server Co nfiguration Manager,click derecho en SQL Server (SQLEXPRESS) y click en reinicar.

2. Habilitar la autenticación por conexión remota

Para resolver este problema. Uno es habilitar el modo de autenticación ambos SQL Server y Windows en el servidor y la otra es habilitar la conexión remota en el nave gador de SQL Server.
      • Chekear que usted tenga permitido el modo bo th SQL Server and Windows Authentication mode (Si usted no usa el modo Windows Authentication). Para la instancia del usuario ‘sa’.
1. Iniciar sesion usando SQL Server Management Studio Express al Servidor SQL y en modo Windows Authentication. Esto podría usar su cuenta de Windows para autenticarse con SQL Server.
2. En el objeto Explorador, click derecho en el nombre de instancia y seleccionar propiedades.


3. Seleccionar la página Security y cambiar la autenticación del servidor al modo SQL Server and Windows Authentication mode y presionar el boton Ok.
4. Click derecho otravés en el nombre de la instancia, seleccionar Restart para reiniciar el Servicio de SQL Server.

5. Esto es todo. Tienes habilitado el modoSQL Server and Windows authenticat ion, ahora usted puede iniciar sesion en SQL Server con su cuenta de Windows o su cuenta creada.

      • Chekear que usted tenga habilitado la conexión remota en Configuración de superficie de SQL Server
1. Abrir Configuración de superficie de SQL Server.


2. Seleccioar Configuracion de superficie para Servicios y Conexiones.


3. En el lado izquierdo, expandir su instancia de SQL Server -> Motor de base de datos -> Conexiones Remotas. En el lado derecho, seleccionar Conexiones locales y remotas -> Usar TCP/IP y canalizaciones con nombre.

4. En el lado izquierdo, seleccionar Explorador de SQL Server -> Servicio.
En el lado derecho, si el tipo de inicio esta Deshabilitado, usted necesita cambiarlo a Automatico. Clik en Aceptar.

5. Iniciar sesion usando SQL Server Management Studio Express al Servidor SQL y en modo Windows Authentication.

6. En el panel Object Explorer , expandir Security / nodo Logins.

7. Seleccionar el usuario "sa".

8. Click derecho en el usuario "sa"->propiedades e ingresar password para este usuario.


9. Luego seleccione la página Status y dele Click en la opcion enable de Login, Click en Ok

10. Click derecho otravés en el nombre de la instancia, seleccionar Restart para reiniciar el Servicio de SQL Server.

Probando lo hecho:

Usted ha finalizado la configuracion. Ahora intente iniciar sesion en su Servidor SQL de forma remota o en su computadora usando el modo SQL Server authentication.


Inicio de sesion a SQL Server con éxito.


sábado, 9 de febrero de 2008

Card PHP Cheat Sheet

Emezeta a realizado un resumen muy bueno de las funciones de php añadiendo pequeñas descripciones muy útiles al momento de buscar alguna información rápida.

Chuleta completa de PHP

sábado, 19 de enero de 2008

Curso de Ajax por el Dr. Diego de Ipiña

domingo, 13 de enero de 2008

Listas Genericas: Novedad en J2SE 5.0

sábado, 12 de enero de 2008

Zend Framework: Paginado (parte I)

Como sabran PHP esta evolucionando, gracias al aporte de todas las personas que comparten algo en común una pasion.

Desde que Ruby on Rails salio, PHP ha tenido que adaptarse al cambio, utilizar el patron modelo vista controlador, a partir de ese momento salieron a la luz muchos frameworks como prado, cakePHP entre otros, pero tambien se creo uno llamado zend framework que es el que utilizaremos para este ejemplo, que consiste en mostrar los resultados en un datagrid paginado, utilizando POO con PHP.

Software utilizado:



Comenzamos ... :$

Clases de utilidad
en primer lugar tengo que mostrar dos clases de persistencia que utilizo:

la clase DBManager.class.php
<?
/********************************************/
/* Clase DBManager */
/*Clase que administra las conexiones con */
/*la base de datos. */
/*Autor: Hugo Flores Joseph 2006 */
/*Copyright (c) */
/********************************************/
require_once('Recordset.class.php');

class DBManager{

private $host='localhost';
private $db ='agenda';
private $user='';
private $pass='';
private $connectionID;// Retorna un enlace identificador de la conexion hecha con la base de datos
private $queryID = -1;// Esta variable guarda elúltimo resultado creado por link identifier de una consultra (almacena un entero<true=1,false=0>)
private $tempResultObj = '';// Almacena el resultado del Objeto Recientemente creado via el método execute()
private $error="";


//----------------Métodos Públicos--------------------//

public function DBManager($user='',$pass='')
{
if(!empty($user))$this->user=$user;
if(!empty($pass))$this->pass=$pass;

try{
$this->connectionID=@mysqli_connect($this->host,$this->user,$this->pass,$this->db);
if(!$this->connectionID) throw new Exception(mysqli_connect_error());
}
catch(Exception $e)
{
echo "A ocurrido un error: ".$e->getMessage();
exit();//termina la ejecucion del script
}
}

//funcion ADHOC utilizada con SELECT
public function executeQuery($sql = "")
{
$this->queryID = mysqli_query($this->connectionID,$sql);
$this->tempResultObj = new Recordset($this->queryID);//Inicializa un objeto sin considerar si la consulta retorna algun resultado o no.
return $this->tempResultObj;
}
//funcion ADHOC utilizada con INSERT, UPDATE, DELETE
public function executeUpdate($sql = "")//devuelve falso si la consulta tuvo exito
{
$resp=false;
$this->queryID = @mysqli_query($this->connectionID,$sql); //Inicializa un objeto sin considerar si la consulta retorna algun resultado o no.
if($this->queryID) $resp=true;
return $resp;
}
public function getConnection() { return $this->connectionID;}
public function closeConnection(){ mysqli_close($this->connectionID);}
}
?>


La segunda clase que utilizaremos es Recordset.class.php, esta clase tiene un comportamiento similar a java.sql.ResultSet de Java:
<?
/********************************************/
/* Clase Recordset */
/* clase que me permite manejar un conjunto */
/* de registros de una base de datos */
/* MySQL. */
/* Autor: Hugo Flores Joseph 2006 */
/* Copyright (c) */
/********************************************/

class Recordset{
//------Variables Públicas---------//
public $fields;
public $BOF = null;// indica que la posición actual del registro esta antes del primer registrp en un Objeto Recordset.
public $EOF = null;// indica que la posición actual del registro esta después del último registro en un Objeto Recordset.

//------Variables Privadas---------//
private $_numOfRows = -1; // No Cambie este valor! SOLO LECTURA!
private $_numOfFields = -1; // No Cambie este valor! SOLO LECTURA!
private $_tempResult = '';// Almacena un valor que fue retornado desde una función específica de la Base de Datos
private $_queryID = -1;// Esta variable guarda el resultado de un link identifier
private $_currentRow = -1;// Esta variable guarda la actual fila en un Recordset.

//------Métodos--------------------//
// Devuelve: query id exitoso o falso si
// la función Constructor ha fallado
public function Recordset($queryID)
{
$this->_queryID = $queryID;
if ($queryID) {
$this->_numOfRows = @mysqli_num_rows($this->_queryID);
$this->_numOfFields = @mysqli_num_fields($this->_queryID);//devuelve el número de campos de la consulta o result set
}
else {
$this->_numOfRows = 0;
$this->_numOfFields = 0;
}
// Si el resultado contiene filas
if ($this->_numOfRows > 0 && $this->_currentRow == -1) {
$this->_currentRow = 0;
$this->fields = mysqli_fetch_array($this->_queryID);//captura la fila en un array mssql_fetch_aaray(Devuelve: Un array que corresponde a la fila capturada, o FALSE si no hay más filas)
$this->EOF = false;
$this->BOF = false;
}
return $this->_queryID;
}//fin de método Recordset

// Devuelve: True si hay todavía filas disponibles, o False
// si no hay mas filas. Mueve a la proxima fila en un
// Objeto Recordset Especifico y hace que el registro de la fila actual
// y la correspondiente informaciónde la fila se recupere
// en la colección de los campos. Note: Al contrario del método moveRow(),
// cuando _currentRow esta getNumOfRows() - 1, EOF podria inmediatamente ser
// True. Si el número de fila no es proporcionado, la funcion podria posicionarse
//automáticamente en la primera fila.
public function nextRow()
{
if ($this->getNumOfRows() > 0)
{
$this->fields = array();
$this->_currentRow++;
$this->fields = @mysqli_fetch_array($this->_queryID);
// Esto esta no trabajando. True todo el tiempo
if ($this->fields)
{
$this->_checkAndChangeEOF($this->_currentRow - 1);
return true;
}
}
$this->EOF = true;
return false;
}//fin de método nextRow()

// Devuelve: true si es exitoso, false si ha fallado moveRow()
// moueve el puntero interno de una fila de el Objeto Recordset
// hacia un puntero de una fila especifico y la correspondiente
// información de la fila que podria recuperarse de la colección de
// campos. Si el número de fila no es proporcionado, la funcion podria posicionarse
// automáticamente en la primera fila.
public function moveRow($rowNumber = 0)
{
if ($rowNumber == 0) {
return $this->firstRow();
}
else if ($rowNumber == ($this->getNumOfRows() - 1)) {
return $this->lastRow();
}
if ($this->getNumOfRows() > 0 && $rowNumber < $this->getNumOfRows()) {
$this->fields = null;
$this->_currentRow = $rowNumber;
if(@mysqli_data_seek($this->_queryID, $this->_currentRow)) {//mueve el puntero interno de las filas Devuelve: TRUE si se ejecuta con éxito, FALSE si falla
$this->fields = @mysqli_fetch_array($this->_queryID);
/* This is not working. True all the time */
if ($this->fields) {
// No necesita llamar a _checkAndChangeEOF() por que
// la posibilidad de mover hacia la última fila ha
// sido manejada por el código de arriba
$this->EOF = false;
return true;
}
}
}
$this->EOF = true;
return false;
}//fin de moveRow()

// Devuelve: true en caso de exito, false en caso de fallo de lastRow() moueve
// el puntero interno de la fila de un Objeto Recordset hacia la última fila
// y recupera la correspondiente información de la fila
// de la collecion de campos.
public function lastRow()
{
if ($this->getNumOfRows() > 0) {
$this->fields = array();
$num_of_rows = $this->getNumOfRows();
$this->_tempResult = @mysqli_data_seek($this->_queryID, --$num_of_rows);//Devuelve: TRUE si se ejecuta con éxito, FALSE si falla y es --$num_of_rows por que en sql
if ($this->_tempResult) { //existe un ultimo registro en blanco entonces tengo que posicionarme en el
/* $num_of_rows decrementado anterioemente */ //penultimo registro.
$this->_currentRow = $num_of_rows;
$this->fields = @mysqli_fetch_array($this->_queryID);
/* Esto no esta trabajando. Verdadero todo el tiempo */
if ($this->fields) {
/* Caso Especial para hacer EOF=fallse. */
$this->EOF = false;
return true;
}
}
}
$this->EOF = true;
return false;
}//fin de método lastRow()

// Devuelve: true en caso de éxito, false en caso de fallo, firstRow() mueve
// el puntero interno de la fila de un Objeto Recordset hacia la primera fila
// y recupera la correspondiente información de la fila
// de la collecion de campos.

public function firstRow()
{
if ($this->getNumOfRows() > 0) {
$this->fields = array();
$this->_currentRow = 0;
if (@mysqli_data_seek($this->_queryID, $this->_currentRow)) {
$this->fields = @mysqli_fetch_array($this->_queryID);
$this->EOF = false;
/* Esto no esta trabajando. Verdadero todo el tiempo */
if ($this->fields) {
return true;
}
}
}
$this->EOF = true;
return false;
}


// Retorna: El número de filas de un resultado.
public function getNumOfRows(){return $this->_numOfRows;}

/* Chequea y Cambia el Estado de EOF. */
public function _checkAndChangeEOF($currentRow)
{
if ($currentRow >= ($this->_numOfRows - 1))
{
$this->EOF = true;
}else{
$this->EOF = false;
}
}

// close() solo necesita ser llamado si esta usando mucha memoria
// al correr su script. libera la memoria.

public function close()
{
$this->_tempResult = @mysqli_free_result($this->_queryID);
return $this->_tempResult;
}
}//fin de la clase
?>
Configurando nuestro proyecto
Una vez que tenemos estas dos clases procederemos a organizar nuestro proyecto siguiendo la estructura de directorio recomendada por el framework dentro del directorio htdocs de Apache, creamos una carpeta llamada zfpaging y los subdirectorios lo siguientes:


application/
controllers/
IndexController.php
models/
views/
scripts/
index/
index.phtml
helpers/
filters/
html/
.htaccess
index.php


La estructura que se muestra es la configuracion por defecto de un proyecto con zend framework, pero lo vamos a adaptar a lo que nostros utilizaremos:

application/
controllers/
IndexController.php
models/
views/
scripts/
index/
index.phtml
helpers/
filters/
.htaccess
library/
paging/
sql/
zend/
.htaccess
public/
images/
scripts/
styles/
.htaccess
.htaccess
index.php

lunes, 24 de diciembre de 2007

Diseño de blogs y usabilidad : Franco Gimenez y Leo Prieto