MySQL tiene la posibilidad de crear columnas que se auto-incrementan en la misma definición de la columna a travé del comando AUTO_INCREMENT, no así PostgreSQL. En Postgres es más complicado, y de esta manera lo hago yo.
1. Crear secuencia
Con pgAdmin III
pgAdmin3 es una aplicación multi-plataforma que sirve para administrar las bases de datos PostgreSQL hecha por la misma comunidad PostgreSQL. Si l quieres hacer por líneas de comandos, avanza un poco más en este artículo.
Una vez abierto el pgAdmnin3 y hecha la conexión:
Expando mi base datos, mi Esquema, elijo con el botón secundario del mouse la sección Secuencias y elijo en el menú contextual la opción Nueva Secuencia...
En el formulario le pongo un nombre (en mi caso se llamará transferencias_id), el usuario que hará uso de esta secuencia (en mi caso, el usurio se llama ooscarr) y OK. También puedo elegir si quier que se auto-incremente a partir de un número diferente al 1 y/o si quiero que el número vaya aumentando de 2 en 2, 3 en 3, etc. en vez de 1 en 1 como se pone por defecto.
Lo mismo, desde la línea de comandos
si seleccionas la nueva secuencia que se agrega a la lista puedes ver el comando SQL que se utilizó para crearla. Lo mismo se pudo haber hecho desde la línea de comandos psql con:
CREATE SEQUENCE transferencias_id;
ó
CREATE SEQUENCE transferencias_id
INCREMENT 1
MINVALUE 1
START 1
CACHE 1;
ALTER TABLE transferencias_id OWNER TO ooscarr;
transferencias_id es el nombre que le asigné a la secuencia y ooscarr es el usuario de PostgreSQL que es dueño de esta variable auto-incrementable.
2. Usar la secuencia en una columna
Con pgAdmin3
Expandemos la tabla que queremos modificar, expandemos Columnas, y seleccionamos la columna de la tabla que se deseas que se auto-incremente con esta variable, vas a las Propiedades....
En el inspector de columna, le asignamos el Valor por defectoNEXTVAL('transferencias_id'). Siendo transferencias_id el nombre de la secuencia.
OK
Con comandos (psql)
Sería...
ALTER TABLE transferencias
ALTER COLUMN id
SET DEFAULT NEXTVAL('transferencias_id');
transferencias_id es el nombre de la secuencia, id es el nombre de la columna a asignarle la secuencia y transferencias es el nombre de mi tabla donde está la columna con al secuencia.
Actualizar filas anteriores sin la secuencia
Con comandos
Para cambiar los valores null de las filas creadas antes de la asignación de la variable auto-incrementable, consultamos:
UPDATE transferencias
SET id = NEXTVAL('transferencias_id');
Ese paso final es una de las cosas más lentas que puedes pedirle a Postgres que haga posiblemente. Para una tabla de tamaño mediano (alrededor de 5,000,000 tuplas, con unas cuantas columnas de pequeños números y textos), eso tomó cerca de 2.5 horas en hardware poderoso - así que querrás dejar esto por un tiempo tranquilo. Afortunadamente Postgres interpreta el UPDATE como una transacción atómica: nada se realiza hasta que el comando se complete, así será difícil que dejes los datos en un estado inconsistente.
Y ya con eso, cada vez que crees una nueva fila en esa tabla, esa columna se llenará automáticamente con un número distinto automáticamente.
Al final de este tutorial conocerás la dinámica del desarrollo de una aplicación web manejando la persistencia de la base de datos con Hibernate y cómo NetBeans IDE te ayuda a escribir el código y consultar la base de datos. También escribirás una aplicación web JSP que haga consultas a esta base de datos a través usando XML.
Este ejemplo de Hibernate es famoso, está documentado en varias páginas, pero todas tienen el código malo y es frustrante aprender así. Así que lo corregí y lo traduje al español sacando cosas de uno y de otro mismo tutorial que encontré en ¡chino, portugués, inglés y ruso!
Soporte para Hibernate en aplicaciones web está disponible desde NetBeans IDE 6.1. Desde NetBeans IDE 6.5, también puedes hacer ingeniería inversa a las tablas de una BD a archivos de mapeo y clases Java correspondientes usando un asistente intuitivo.
Pasos previos
Antes de empezar necesitarás:
Instalar NetBeans IDE. Al momento de escribir esto, anda dando vueltas la versión 6.8 RC2.
Instalar MySQL o Java DB, o tener acceso a conectarte a una de estas bases de datos con permiso para acceder o crear la base de datos Sakila. La base de datos Sakila está disponible en estos dos tipos de bases de datos, pero Hibernate funciona con cualquier JDBC, por ejemplo PostgreSQL y Oracle.
Una vez obtenido esto, asegúrate de configurar NetBeans IDE para poder acceder a la base de datos Sakila desde el panel "Prestaciones" (Menú Ventana > Prestaciones.
Instalar el complemento de Hibernate
El plug-in, si no lo tienes ya instalado, lo obtienes
yendo, en el menú, a Herramientas > Complementos.
En la ficha Plugins disponibles, selecciona la casilla del módulo Hibernate y presiona Instalar.
Siguiente
Acepta los términos de todos los contratos de licencia y presiona el botón de Instalar.
Después que se descargue y se instale, presiona Terminar.
Y listo, el módulo para Hibernate (o Hibernar) se activará solo; o sino, reinicia NetBeans IDE.
Crear Proyecto nuevo
Primero: lo típico. Creamos un Proyecto nuevo de tipo Aplicación web.
Para nuestro ejemplo, le damos el nombre DVDStore.
Elegimos un servidor como Tomcat o Glassfish, Siguiente y marcamos la opción Hibernate y seleccionamos la base de datos jdbc:mysql://localhost:3306/sakila, en nuestro caso, de la lista que, supongo, ya habías configurado anteriormente como indiqué en los pasos previos de este tutorial.
Terminar
Fíjate que en:
DVDStore
Libraries
se agregaron automáticamente las librerías necesarias para utilizar Hibernate y conectar a la base de datos.
Configurar proyecto
hibernate.cfg.xml
Abre el archivo hibernate.cfg.xml que está en la ruta:
DVDStore
Source Packages
<paquete predeterminado>
hibernate.cfg.xml
Una vez abierto en NetBeans IDE, en el modo Diseño, en la parte Propiedades opcionales, Propiedades de configuración, pon Agregar... y añade la propiedad:
Nombre de la propiedad:
hibernate.show_sql
Valor de la propiedad:
true
Dentro de las mismas Propiedades opcionales del modo Diseño de NetBeans IDE, más abajo, en Propiedades varias, Agrega la propiedad:
Nombre de la propiedad:
hibernate.current_session_context_class
Valor de la propiedad:
thread
Después de esto, si ves el archivo hibernate.cfg.xml en el modo Operador XML, quedaría un código más o menos así, pero con otras contraseñas, por supuesto:
Archivos de mapas de Hibernate y POJOs de la base de datos
Crea un Archivo nuevo.... Categoría Hibernar, tipo Archivos de mapas de Hibernate y POJOs de la base de datos.
Debes ponerle nombre a la clase donde estarán los mapas de Hibernate. Para que este tutorial funcione, ponle dvdrental
...y presiona el botón Terminar. Se deberían generar los siguientes archivos:
DVDStore
Source Packages
dvdrental
Actor.hbm.xml
Actor.java
Category.hbm.xml
Category.java
Film.hbm.xml
Film.java
FilmActor.hbm.xml
FilmActor.java
FilmActorId.java
FilmCategory.hbm.xml
FilmCategory.java
FilmCategoryId.java
Language.hbm.xml
Language.java
HibernateUtil.java
Lo último sería crear un Archivo Nuevo..., Categoría Hibernar, Tipo HibernateUtil.java.
Terminar
Empecemos
FilmHelper.java
Crea una nueva Clase Java (Archivo Nuevo..., Categoría Java, tipo Clase Java) y llámale FilmHelper y ponlo dentro del paquete dvdrental.
Terminar
Agrega el siguiente código (en negrita) para crear una sesión de Hibernate.
package dvdrental;
public class FilmHelper {
Session session = null;
public FilmHelper() {
this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}
}
Van a aparecer unos errores que se arreglan usando el menú contextual (botón secundario del ratón) y eligiendo la opción Reparar importaciones.
La opción Reparar importaciones en inglés se llama Fix import.
Si dejamos el valor por defecto, quedaría el código de FilmHelper.java de la siguiente manera:
package dvdrental;
import org.hibernate.Session;
public class FilmHelper {
Session session = null;
public FilmHelper() {
this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}
}
Consultas HQL
Probemos algo. Haz click con el botón secundario sobre el archivo Source Packages/<paquete predeterminado>/hibernate.cfg.xml y selecciona la opción Ejecutar la consulta HQL del menú contextual.
En la barra de herramientas del editor de consultas HQL, selecciona la Sesión: hibernate.cfg y escribe lo siguiente en la primera caja de texto grande:
from Film
Y presiona el botón que está al lado de la lista desplegable que debería estar mostrando hibernate.cfg como opción seleccionada para hacer la consulta y obtener un resultado como el siguiente.
Ahora prueba con una consulta un poquito más complicada:
from Film as film where film.filmId between 100 and 200
Con las consultas probadas, obteniendo los resultados esperados, podemos utilizarlas en la clase helper.
Hibernate
Edita el archivo FilmHelper.java y agrégale el siguiente método (marcado con negrita):
package dvdrental;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
public class FilmHelper {
Session session = null;
public FilmHelper() {
this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}
// Obtiene los films donde el id de film está entre un cierto rango especificado por las variables startID y endID
public List getFilmTitles(int startID, int endID) {
List<Film> filmList = null;
try {
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Film as film where film.filmId between '" + startID + "' and '" + endID + "'");
filmList = (List<Film>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return filmList;
}
}
Repara las importaciones (Fix Import) si es necesario, utilizando las clases de hibernate.
para que quede completamente igual como está en el código de ejemplo anterior.
Vuelve a abrir el Editor de Consultas HQL y haz la siguiente query:
from Actor as actor where actor.actorId in (select filmActor.actor.actorId from FilmActor as filmActor where filmActor.film.filmId='10')
Esta consulta obtiene los actores de la película del filmid = 10.
Ahora súmale el siguiente método (marcado con negrita) al archivo FilmHelper.java:
package dvdrental;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
public class FilmHelper {
Session session = null;
public FilmHelper() {
this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}
// Obtiene los films donde el id de film está entre un cierto rango especificado por las variables startID y endID
public List getFilmTitles(int startID, int endID) {
List<Film> filmList = null;
try {
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Film as film where film.filmId between '" + startID + "' and '" + endID + "'");
filmList = (List<Film>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return filmList;
}
// Obtiene los actores en un film particular
public List getActorsByID(int filmId) {
List<Actor> actorList = null;
try {
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Actor as actor where actor.actorId in (select filmActor.actor.actorId from FilmActor as filmActor where filmActor.film.filmId='" + filmId + "')");
actorList = (List<Actor>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return actorList;
}
}
Repara las importaciones si es necesario. Guarda.
Ahora agrega 3 métodos más y algunos métodos que inventé para hacer uso de beans en el código JSPX.
package dvdrental;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
public class FilmHelper {
Session session = null;
public FilmHelper() {
this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}
// Obtiene los films donde el id de film está entre un cierto rango especificado por las variables startID y endID
public List getFilmTitles(int startID, int endID) {
List<Film> filmList = null;
try {
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Film as film where film.filmId between '" + startID + "' and '" + endID + "'");
filmList = (List<Film>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return filmList;
}
// Obtiene los actores en un film particular
public List getActorsByID(int filmId) {
List<Actor> actorList = null;
try {
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Actor as actor where actor.actorId in (select filmActor.actor.actorId from FilmActor as filmActor where filmActor.film.filmId='" + filmId + "')");
actorList = (List<Actor>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return actorList;
}
// Obtiene una lista de categorías de acuerdo al filmId
public Category getCategoryByID(int filmId) {
List<Category> categoryList = null;
try {
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Category as category where category.categoryId in (select filmCat.category.categoryId from FilmCategory as filmCat where filmCat.film.filmId='" + filmId + "')");
categoryList = (List<Category>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return categoryList.get(0);
}
// Obtiene un solo film de acuerdo al filmId
public Film getFilmByID(int filmId) {
Film film = null;
try {
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Film as film where film.filmId=" + filmId);
film = (Film) q.uniqueResult();
} catch (Exception e) {
e.printStackTrace();
}
return film;
}
// Obtiene el idioma del film de acuerdo a un langId
public String getLangByID(int langId) {
Language language = null;
try{
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Language as lang where lang.languageId=" + langId);
language = (Language) q.uniqueResult();
} catch (Exception e) {
e.printStackTrace();
}
return language.getName();
}//Métodos para no poner código java en el JSPX
int startId;
int endId;
int filmId;
int langId;
public void setAttributeStartID(int startId){
this.startId = startId;
}
public void setAttributeEndID(int endId){
this.endId = endId;
}
public List getFilmTitlesList(){
return getFilmTitles(startId,endId);
}
public void setAttributeFilmByID(int filmId){
this.filmId = filmId;
}
public List getActorsID() {
return getActorsByID(filmId);
}
public Category getCategoryID() {
return getCategoryByID(filmId);
}
public Film getFilmID() {
return getFilmByID(filmId);
}
public void setAttributeLangByID(int langId){
this.langId = langId;
}
public String getLangID() {
return getLangByID(langId);
}
}
JSP(X)
Hurra. Por fin llegamos a las páginas web. A mi me gusta escribir las JSP con JSTL así que antes de seguir deberás...
Instalar la librería JSTL
Entra a las propiedades del proyecto (botón secundario del ratón sobre DVDStore, opción Propiedades).
En la sección Libraries hay un botón Add Library.... Presiónalo.
Si no te aparece inmediatamente, Importa la librería (o biblioteca también le llaman) JSTL 1.1 o superior.
Selecciona la librería JSTL y añádela al proyecto.
Aceptar
Nuevo archivo JSPX
Primero elimina el archivo index.jsp del proyecto que está en la carpeta DVDStore/Web Pages/ del proyecto.
Ejecuta la aplicación en el servidor, visita la página (en mi máquina se está ejecutando en http://localhost:8084/DVDStore/) y Voilà!. Funciona o te equivocaste.
Conclusiones
A pesar de que este ejemplo sólo hace lecturas a la base de datos, me puedo imaginar que escribir debe ser igual de sencillo ya que autmáticamente se generan la clases bean para insertar valores (set).
Con la persistencia ya no me tengo que preocupar de hacer la conexión y desconexión en cada página, la contraseña está guardada de manera más segura y estandarizada, y el acceso a las tablas se hace sencillo manejándolas como clases (un editor de Java ayuda a completar el código) y no andan las consultas SQL dando vueltas por todo el código, lo que ofrece mayor abstracción entre los distintos niveles del código otorgando flexibilidad a cambios.
Si se me ocurre cambiar la base de datos (agregar una columna, modificar el nombre de una tabla o las relaciones y tipos de datos), habría que regenerar los mapas de Hibernate y volver a compilar todo.
También, si nos fijamos en todo lo que hay que saber sobre programación Java, se hace más difícil la programación, aunque supongo y reconozco que con el tiempo se debe volver más sencillo con la experiencia. Obvio.
Mejoras en el rendimiento... No sé. Supongo que al tener todas las consultas guardadas... Y con Hibernate preocupado de las conexiones y desconexiones... Me imagino que sí hay alguna mejora, lo desconozco.
En el próximo capítulo...
Esto fue cómo leer desde una base de datos con Hibernate, prometo escribir sobre cómo escribir en la base de datos usando Hibernate y hacer este mismo ejemplo usando JPA, que ya lo tengo hecho, pero hay que desarrollarlo y darle formato. Hasta el próximo mes.
Con el software opensource de virtualización de escritorios VirtualBox puedes probar ya el nuevo sistema operativo de Google completamente gratis y fácilmente en una ventana gracias a la posibilidad de abrir imágenes VMWware. Jump the shark.
Instrucciones
Consigue una imagen de Chrome OS ya compilada (anda una imagen VMware dando vueltas por ahí).
Mueve el archivo .vmdk a una carpeta personal, por ejemplo Mis documentos o ~/Library/VirtualBox/HardDisks o en cualquier lugar que no se te pierda.
Dale un nombre, en Sistema Operativo elije la opción Linux y en Versión: Other Linux. Siguiente.
Especifica la memoria base. 256MB es lo mínimo recomendado, luego Siguiente.
En el paso siguiente, marca la casilla de Disco duro de arranque (Primario maestro), selecciona la opción Usar un disco duro existente y busca la imagen VMWare de Chrome OS que conseguiste.
Siguiente. Terminar. Ahora selecciona la nueva máquina virtual de la lista que tiene VirtualBox e iníciala.
Ahí está. El usuario y contraseña son los mismos que usas para iniciar sesión en Google.
En http://developer.palm.com/ puedes descargar, previo registro, un instalador del WebOS (el sistema operativo que usa el Palm pre) para VirtualBox gratis también para jugar.
Con el plug-in de Netbeans, instalar la base de datos de ejemplo Sakila es sencillo (con los permisos adecuados).
La base de datos de ejemplo Sakila fue desarrollada por Mike Hillyer, un pasado miembro del equipo de documentación de MySQL AB, y su intención fue la de proveer un esquema estándar que pueda ser usado para ejemplos en libros, tutoriales, artículos, ejemplos, y así en adelante. La base de datos de ejemplo Sakila también sirve para destacar las últimas características de MySQL tales como Vistas, Procedimientos Almacenados, y Disparadores (Triggers).
Diagrama relacional del Scheme de Sakila DB (ver más grande)
Instalar el plug-in de Sakila es muy sencillo, sólo vamos al menú Herramientas > Complementos, en el panel que se abre, existe una sección llamada Plugins disponibles.
Para instalarlo, espera que cargue la larga lista de plugins disponibles, marca la casilla de Sakila Sample Database y presiona el botón Instalar que está debajo. Sigue el proceso de instalación, reinicia Netbeans IDE si es necesario.
Luego, en el panel de Servicios (si no lo ves, elije el menú Ventana > Prestaciones) y con el menú contextual sobre la parte de Bases de datos elije la opción Registrar servidor MySQL... si todavía no lo has hecho.
Ya, cuando te hayas conectado al servidor MySQL como root u otra cuenta con los suficientes permisos, selecciónala y en el menú contextual elije la nueva opción Crear base de datos....
En el cuadro de diálogo que se abre, seleccionamos sakila en el primer campo, y en el segundo seleccionamos al usuario que tendrá todo el poder sobre esta nueva base de datos.
Ya, con eso, después de esperar que se creen todas las tablas y se llenen de datos de ejemplo, podemos conectarnos y empezar a utilizarlas para nuestros experimentos y lecciones.
Voy a borrar toda una base de datos usando las líneas de comandos.
Eliminar una base de datos involucra eliminar también todas las tablas y contenidos de éstas y para hacerlo se necesita tener permiso para borrar dicha base de datos, y en mi caso usaré la cuenta root.
Voy al terminal, e inicio sesión como root:
/usr/local/mysql/bin/mysql -u root -p
Si el usuario root tiene contraseña, la ingresamos.
El comando para borrar una base de datos, según la documentación oficial, es:
DROP {DATABASE | SCHEMA} [IF EXISTS] db_name
Por ejemplo, para el caso que quiera eliminar una base de datos llamada ooscarr, pondría:
DROP DATABASE IF EXISTS ooscarr;
Obviamente, se advierte precaución ya que si no se ha hecho un respaldo previo, los datos no se podrán recuperar.
Si estás usando un Mac con un procesador de 64 bits (como un Core 2 Duo o Core i5, i7) y tienes algún Leopardo (OS X 10.5 u OS X 10.6) mejor descarga la versión de 64 bits para ir acorde a Apache2 que se ejecuta a 64 bits.
2. Leer antes de instalar
Si usas Mac OS X Server te recomiendo que leas el archivo Readme.txt que viene con el DMG para leer la documentación (en inglés) ya que Mac OS X Server viene con MySQL pre-instalado.
Aún si no usas la versión server, puede que ya tengas MySQL previamente instalado. Revisa si lo tienes instalado buscando algún archivo o carpeta con la palabra "mysql" en la carpeta /usr/local ó en Librería/StartupIyems, ya sea con el Finder (Menú Ir > Ir a la carpeta...) o con el Terminal:
ls /usr/local
ls /Library/StartupItems
Otra opción es ejecutar el comando de apagar el servidor MySQL que podría estar corriendo (y que es necesario hacerlo antes de comenzar la instalación) con el comando:
mysqladmin shutdown
Si no existe el comando, estamos bien. De todos modos, el instalador archivará una versión antigua de MySQL con la extensión .bak (siempre que el servidor MySQL haya sido parado antes de instalar).
3. Asistente de instalación
Ahora instala el paquete de instalación que NO se llama "MySQLStartupItem.pkg" y el rutinario Siguiente, Siguiente, Instalar, Finalizar.
El instalador te puede decir que no hay espacio, es un bug; retrocede y vuelve a intentarlo y no debería pasar.
Ojo, el instalador requiere un usuario llamado "mysql", pero los buenos de Apple lo crearon durante la instalación del sistema operativo. :-)
Configurar Mac OS X
Iniciar servidor
Iniciar y apagar MySQL es mucho más fácil y gráfico si se instala el panel de preferencias del sistema abriendo el archivo MySQL.prefPane incluido en la DMG de instalación de MySQL.
Con esto, iniciar o detener el servidor MySQL es muy sencillo; basta presionar un botón en el panel de Preferencias del sistema MySQL, incluso se puede configurar para que se inicie automáticamente cuando arranque el sistema sin necesidad de modificar archivos de sistema.
PHP
Apple fue lo suficientemente amable para compilar php con soporte para MySQL así que sólo hay que configurar el archivo php.ini.
Primero ve a la carpeta /etc ó /private/etc, si ves algún archivo llamado php.ini no sigas el siguiente comando que consiste en crear una copia del archivo php.ini.default para usarlo como php.ini. Las intrucciones para el Terminal son las siguientes:
cd /etcsudo cp php.ini.default php.ini
Edita el archivo recién creado con permisos de administrador con la instrucción:
sudo pico php.ini
Presiona control + W, busca mysql.default_socket, y hazlo que se vea como esto:
mysql.default_socket = /tmp/mysql.sock
Guarda los cambios presionando controlX, luego presiona Y, luego presiona enter.
Si tenías el Compartir web corriendo, reinicia Apache desactivándolo y volviéndolo a activar.
Si quieres hacer una prueba, crea el siguiente archivo:
Entonces todo salió bien. Si no, quizás todavía no has configurado Apache para que funcione con PHP o qué sé yo.
Configurar bases de datos inciales
Durante la instalación por defecto de MySQL, se crearon unas cuentas de usuario:
root
El usuario root tiene acceso de super-usuario a todas las bases de datos, sólo se puede conectar desde el computador local y por defecto no lleva contraseña.
Cuentas anónimas
Dos cuentas de usuario anónimas son creadas y tampoco llevan contraseña, y sólo se puede conectar a ellas desde el local-host. Estas cuentas tienen todos los privilegios para la base de datos de prueba (test) y para otras bases de datos con nombres que empiezan con test_.
Cambiar las contraseñas por defecto
Primero debes averiguar cuáles son las cuentas que se crearon; para eso, voy al Terminal y primero me conecto como root:
/usr/local/mysql/bin/mysql -u root
...listo las cuentas con la consulta:
mysql> SELECT Host,User FROM mysql.user ORDER BY User DESC;
Para cambiar estas 5 contraseñas que están en blanco por el momento, escribo las siguientes consultas:
mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('contraseña_root');
mysql> SET PASSWORD FOR 'root'@'MacBook.local' = PASSWORD('contraseña_root');
mysql> SET PASSWORD FOR 'root'@'127.0.0.1' = PASSWORD('contraseña_root');
mysql> SET PASSWORD FOR ''@'localhost' = PASSWORD('contraseña_anónima');
mysql> SET PASSWORD FOR ''@'MacBook.local' = PASSWORD('contraseña_anónima');
Obviamente, reemplazando contraseña_root por la clave que le quieras poner al super-usuario, y las contraseña_anónima por la de las cuentas anónimas.
Desde ahora, la próxima vez que ingreses a MySQL con una cuenta que requiera contraseña, deberás agregar el parámetro -p al final, por ejemplo:
Ahora voy a crear una base de datos nueva llamada "db_name". Para eso, entro a MySQL como root y escribo:
CREATE DATABASE IF NOT EXISTS db_name;
Crear un nuevo usuario
Pata crear un nuevo usuario escribimos (como rootMySQL):
CREATE USER 'ooscarr'@'localhost' IDENTIFIED BY 'obscure';
Con esto se creará el usuario "ooscarr" con la contraseña "obscure" para que se conecte desde localhost. Si queremos que pueda acceder desde otro equipo, habría que hacer lo mismo que se hizo anteriormente con los dominios o la dirección IP listados, que en mi caso sería:
CREATE USER 'ooscarr'@'MacBook.local' IDENTIFIED BY 'obscure';
CREATE USER 'ooscarr'@'127.0.0.1' IDENTIFIED BY 'obscure';
Asignar base de datos a un usuario
Ya, finalmente, le damos el permiso al usuario "ooscarr" recién creado para que administre la base de datos db_name, por ejemplo, con la siguiente sentencia SQL:
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON db_name.*
TO 'ooscarr'@'localhost';
Y como uno se puede imaginar:
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON db_name.*
TO 'ooscarr'@'MacBook.local';
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON db_name.*
TO 'ooscarr'@'127.0.0.1';
Para salir de MySQL escribimos exit; y para salir del Terminal, tipeamos logout.
Instalar software para trabajar con MySQL
Existen herramientas más cómodas para utilizar una base de datos MySQL, como son las interfaces gratuitas phpMyAdmin, Netbeans IDE y la sensacional Sequel Pro, entre otros.
Importante
En el futuro si lo actualizas, asegúrate de hacerle un dump a tus bases de datos, ya que haciendo una instalación sobre una instalación existente destruirá tu directorio de datos.
Era cosa de tiempo para que los empleados de Sun Microsystems comenzaran a recomendar Oracle DB. Aquí dejo el link sobre su instalación en sistemas Mac OS X escrito por Arun Gupta.
En este tutorial voy a mostrar la manera de generar un archivo compatible con Microsoft Excel que consiste en valores separados por espacios tabuladores muy elemental y sin gráficos o estilos.
Primero hay que partir diciendo qué opciones de formatos compatibles con Excel hay:
CSV
Es el más conocido, y consiste en un archivo de texto plano, generalmente con la extención .csv donde los valores de cada celda van separados por una coma (,) en el caso de las columnas, y un salto de línea para las filas.
TSV
TSV es una variación al anterior CSV, donde las columnas van separadas por un espacio tabulador y las filas por un salto de línea. Esto permite que se puedan introducir celdas con valores que incluyan una coma y no sean confundidas por un salto de columna, por ejemplo.
XLS
El formato Microsoft Excel tradicional que es un archivo binario para Windows donde se guardan en hojas, gráficos y macros. Mucho tiempo su especificación fue cerrada, pero desde que se comenzó a documentar el formato con ingeniería inversa y debido a las presiones de las cortes para aceptar su formato como un estándar, Microsoft se vio obligada a publicar su estructura de funcionamiento bien particular.
XLSX
Esta es la última especificación Office Open XML que Microsoft no sé cómo logró estandarizar, y que consiste en una serie de archivos XML y otros, organizados en una carpeta todo comprimido en un archivo ZIP (al igual que el estándar OpenDocument que también es soportado por Microsoft Office 2007 pero que no es de propiedad de Microsoft).
Para una tarea tuve que hacer un manual de cómo instalar un archivo .war en el viejo Tomcat. Super sencillo y básico, no se asombren.
No a la guerra.
En computación, un archivo WAR (el cual sus iníciales significan “archivo de aplicación web”) es un archivo JAR utilizado para distribuir una colección de JavaServer Pages, servlets, clases Java, archivos XML, librerías de tags y páginas web estáticas (HTML y archivos relacionados) que juntos constituyen una aplicación web.
1. Abrir la página inicial de Tomcat
Tomcat manager viene incluido con tomcat cuando se instala, para acceder a él se ingresa a la página del servidor donde está ejecutándose Tomcat.
Usualmente se encuentra en el http://localhost:8080/ o en el mismo puerto del servidor externo.
2. Entrar a Tomcat Manager
En dicha página en la columna de Administración izquierda se encuentra un link a Tomcat Manager
Inmediatamente preguntará por la constraseña, que por defecto es
usuario
tomcat
contraseña
tomcat
En la página de Tomcat manager, aparece una lista con todas las aplicaciónes que Tomcat tiene instaladas o ejecutándose (incluyéndose a sí mismo).
3. Desplegar aplicación
Casi al final, aparece un formulario llamado Desplegar.
En la parte donde dice Seleccione archivo WAR a deplegar, es cosa se buscar el archivo WAR, subirlo al servidor con el botón Desplegar...
Y si no había otra aplicación con el mismo contexto, debería aparecer un mensaje de OK en la parte superior de la página al terminar la transferencia.
Advertencias
No todos los .war funcionan en todas las versiones de Tomcat
ebay ofrece sus servicios web en diferentes formatos de pedido y respuesta como se muestra en la siguiente figura.
En esta ocasión no utilizaremos SOAP para hacer los pedidos, en vez de eso, haremos las requests por medio de URL (a lo REST), pero por lo menos lo que recibiremos será SOAP.
JavaBean
Creamos una nueva clase java.
La nombro, por ejemplo, BuscaItems y la agrego a un paquete, eeh.. consumidor.
BuscaItems.java
En el archivo .java escribo el código correspondiente a un bean, muy parecido al código de la clase java anterior
package consumidor;
import javax.xml.ws.BindingProvider;
public class BuscaItems {
public String que="No definido";
public String consulta="No definida";
public String estado="No procesado";
public Integer nitems=0;//Número de items
public String url="";
private static final String APPID = "UNAP3d995-2kj53-67u8-abcc-po988l9u035";
private static final String CALLNAME = "FindItems";
private static final String VERSION = "557";
private static final String BASEURL="http://open.api.ebay.com/shopping?";
private static BindingProvider bp;
//Constructor
public BuscaItems(){
}
public void setQue(String que){
String endpointURL = BASEURL+"callname=" + CALLNAME+"&version="+VERSION+"&appid=" + APPID;
try { // Llama Operación del Servicio Web
ebay.apis.eblbasecomponents.Shopping service = new ebay.
apis.eblbasecomponents.Shopping();
ebay.apis.eblbasecomponents.ShoppingInterface port = service.
getShopping();
bp = (BindingProvider) port;
bp.getRequestContext().
put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
endpointURL);
// Inicializa los argumentos de la operación del SW
ebay.apis.eblbasecomponents.
FindItemsRequestType findItemsRequest = new ebay.
apis.eblbasecomponents.FindItemsRequestType();
findItemsRequest.setQueryKeywords(que);
// Procesa los resultados
ebay.apis.eblbasecomponents.FindItemsResponseType result = port.findItems(findItemsRequest);
consulta=endpointURL;
estado=result.getAck().toString();
nitems=result.getTotalItems();
url=result.getItemSearchURL();
} catch (Exception ex) {
estado=ex.getMessage();
}
}
public String getConsulta(){
return consulta;
}
public String getEstado(){
return estado;
}
public Integer getNitems(){
return nitems;
}
public String getUrl(){
return url;
}
}
Nuevo JSPX
Biblioteca JSTL
Porque voy a usar <c:choose>, <c:when>, <c:otherwise>, <c:if> y <c:out>, y porque lo hice en Tomcat, es necesario agregar la biblioteca JSTL.
Para eso, en las propiedades del proyecto, en la sección Librerías presionamos el botón Add Library... (Añadir biblioteca...)
Y añadimos la biblioteca JSTL.
index.jspx
Para hacerlo más entretenido, la JSP la escribiré en el nuevo formato de etiquetas, así que crea un nuevo archivo JSP 2.0, e ingresa lo siguiente:
<?xml version="1.0" encoding="UTF-8"?>
<!--
Document : index
Created on : 06-ene-2009, 23:47:10
Author : ooscarr
-->
<jsp:root
xmlns:jsp="http://java.sun.com/JSP/Page"
version="2.0"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<jsp:output
omit-xml-declaration="no"
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
doctype-root-element="html"/>
<jsp:directive.page contentType="text/html" pageEncoding="UTF-8"/>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>JSP Page</title>
</head>
<body>
<div class="encabezado">
<h1>¿Tebay?</h1>
<p>Nombra un producto y te diré si se encuentra en el sitio de ebay.</p>
</div>
<!-- Formulario de consulta -->
<h2>Consulta</h2>
<form action="index.jspx" method="get"><p>
<c:choose>
<c:when test="${empty param.que}">
<input type="text" name="que"/>
</c:when>
<c:otherwise>
<input type="text" name="que" value="${param.que}"/>
</c:otherwise>
</c:choose>
<button type="submit">Buscar</button>
</p></form>
<p>(Se obtienen mejores resultados con consultas en inglés).</p>
<!-- Si se consultó algo -->
<c:if test="${not empty param.que}">
<h2>Resultados de la búsqueda "<c:out value="${param.que}" />"</h2>
<jsp:useBean id="b" scope="page" class="consumidor.BuscaItems">
<jsp:setProperty name="b" property="que" value="${param.que}"/>
</jsp:useBean>
<c:set var="cuantos">
<jsp:getProperty name="b" property="nitems"/>
</c:set>
<c:choose>
<c:when test="${cuantos > 0}">
<!-- La intención de guardar esta variable es para
procesarla con c:out -->
<c:set var="url">
<jsp:getProperty name="b" property="url"/>
</c:set>
<p>Se encontraron
<jsp:element name="a">
<jsp:attribute name="href">
<!-- Al procesar con c:out los "&" se convierten en "%amp;" -->
<c:out value="${url}"/>
</jsp:attribute>
<jsp:body>
<jsp:getProperty name="b" property="nitems"/>
resultados en ebay
</jsp:body>
</jsp:element>
</p>
</c:when>
<c:otherwise>
<p><jsp:element name="a">
<jsp:attribute name="href">
<jsp:getProperty name="b" property="consulta"/>
</jsp:attribute>
<jsp:body>No hubieron resultados</jsp:body>
</jsp:element>.</p>
</c:otherwise>
</c:choose>
</c:if>
<hr /><p>Oscar Fernández</p>
</body>
</html>
</jsp:root>
Resultado
Al presionar el botón Ejecutar (), después de compilar y hacer Deploy automáticamente, se debería abrir la página http://localhost:8084/Tebay/index.jspx parecida a la siguiente:
* La página es sólo de referencia. No funciona.
Conclusiones
Este método claramente se demora debido a que debe comunicarse con los servidores de ebay antes de generar la página de resultado, por lo que el uso de estos servicios web en servidores externos son más recomendables procesarlos en el computador del cliente por medio de técnicas como, en el caso de la web, Javascript (bueno, AJAX).
Esto es un blog escrito por un tal Oscar desde Iquique (Chile), para compartir y comunicarse con el resto de la comunidad de Internet. También escribo opiniones y HOW-TOs a pedido.