Archivos para 20/10/08

Introduccion a JPA (Java Persistence API)

Vamos a programar un poco…

Antes cuando tenia que hacer una consulta en la base de datos, empleaba JDBC a “pelo” o Frameworks como iBatis e Hibernate. Eran APIs que permiten mapear una clase Java (Bean) con una tabla de la base de datos y facilitan mucho el trabajar con la persistencia de los objetos (usando metodos del estilo a “select”, “insert”, “update” y “delete”).

Pero ahora he conocido JPA y me parece que a partir de ahora sera lo unico que utilizare. Con JPA puedes hacer cosas como estas:

- Escribir el codigo de tu clase, y aunque no exista la tabla correspondiente en la base de datos, no importa!!. JPA se encargara de crear la tabla del modelo de datos. Esto esta Genial!!!, es decir, tu solo escribes el codigo y JPA con su mecanismo de persistencia ya se encargara de crear la tablas, si no existen y si existen pues las usa. Ademas da igual la base de datos, podrias por ejemplo escribir la aplicacion en MySQL y despues con un ligero cambio llevartela a Oracle.

- Sincronizacion. Viene tu jefe de proyecto y te dice, quiero que añadas dos columnas nuevas a esta tabla y elimines el campo primario de esta otra tabla. Y ya empiezas a sudar. Llevas escritas mas de 20 sentencias SQL y te toca cambiarlas. Eso se acabo. Es tan sencillo como irte al codigo de tu bean, y añadir 2 atributos nuevos que se mapearan como campos nuevos de la tabla. Chachi.

- Puedes tambien mantener la persistencia no necesariamente atacando a una base de datos, tal vez te interesaria persistir un objeto a un fichero de texto plano o XML.

Como ejemplo de uso de JPA vamos a implementar un pequeño sistema CMS personal. La idea es escribir una pequeña aplicacion que nos permita almacenar nuestros documentos en la base de datos. Y al decir “almacenar” me refiero a almacenar el contenido del documento en la propia base de datos, no su pathname o ruta en el disco duro. De esta manera aprovecharemos para ver como con JPA se hace tambien muy simple la insercion en campos BLOB de la base de datos, algo que muchas veces trae de cabeza a los desarrolladores de Java.

Este ejemplo de CMS (cuyo codigo dejo al final del articulo) sera muy simple. He preferido que el ejemplo no se complique con restricciones o constraints de la base de datos, asi que no existen tampoco claves foraneas a otras tablas. De manera que sera dificil que nos de un error, cuando intentemos insertar algun contenido. Tambien en esta primera version solo os dejare una aplicacion en modo consola (un interprete de comandos) que nos permitira ir insertando o consultando los documentos de nuestra base de datos. En otro articulo posterior, veremos como crear un interface grafico via web que nos permita manipular los documentos.

¿Que necesitamos?

- Pues un editor de Java. Puedes usar el que mas rabia te de. Eclipse, Netbeans u otro. Yo esta vez he usado Netbeans, para ir variando.
- Una base de datos. El ejemplo esta preparado para MySQL pero funcionara con ligeros cambios en Oracle u otra base de datos relacional. A su vez, no te olvides de incluir el driver JDBC de conexion a la base de datos en el Classpath.
- y por ultimo y lo mas importante, para trabajar con JPA necesitamos una implementacion de JPA. Existen muchos fabricantes que han hecho la suya (ver implementaciones). En el ejemplo yo he empleado EclipseLink, asi que basicamente, descargate esta implementacion, descomprimela y copia los siguientes .jar en el classpath de tu proyecto:

- eclipselink.jar
- javax.persistence_1.0.0.jar

En Netbeans podemos por ejemplo crear una Libreria con esos jar, que luego incluiremos en el proyecto, en Eclipse, pues bastaria con añadirlos al classpath.

Ya tenemos todo lo que necesitamos para trabajar, pero no esta de mas que te bajes la siguiente tarjeta de referencia de JPA.

Y ya puestos, la siguiente, que nunca esta de mas.

JPA trabaja fuertemente con anotaciones. Para mapear un bean (una clase java) con una tabla de la base de datos, tendriamos que escribir lo que se llama un Entity.
Esto es tan sencillo como escribir nuestro Bean, con sus atributos y metodos get y set. Y despues añadirle la anotacion “@Entity” a la par que seleccionamos uno de sus atributos como clave primaria con “@Id”. Por ejemplo, el siguiente trozo de codigo podria ser un Entity, que nos permitiria luego almacenar, recuperar, o actualizar campos sobre una tabla “usuario”:

@Entity
public class Usuario
{
@Id
private String id;
private String name;
private String email;
}

Con solo esto ya tenemos creada una “entidad” llamada “Usuario” y podriamos insertar, actualizar o eliminar entradas en una tabla llamada “Usuario” aunque esta aun no existe, siquiera. A que mola!!

Un fichero muy importante que tenemos que crear a parte de las clases “Entity” es el fichero “persistence.xml”, en este fichero vamos a indicar precisamente que clases son Entity, sobre que base de datos vamos a atacar, y cual es la politica de creacion de esta base de datos.
Este fichero “persistence.xml” debe colgar de un directorio “META-INF” que este accesible en el CLASSPATH. Esto es, si tu codigo por ejemplo lo estas dejando en la carpeta “src”, tendras que crear una carpeta “src/META-INF” y ahi dentro crear el fichero “persistence.xml”.
El contenido de este fichero es similar al que puedes ver en la siguiente imagen:

Fijate en el XML un momento:

- Tiene un nombre “DOCSPU” en el tag , este es importante, pues luego es por ese nombre por el que podremos acceder a este recurso o unidad de persistencia. Aqui se llama “DOCSPU” pero puedes darle el nombre o alias que quieras.

- Entre y vamos añadiendo todas las clases Entity que queremos manipular. Esto tambien es muy importante, porque si creas un Entity pero no lo añades a esta seccion del XML, para JPA no existe.

- Y por ultimo estan los properties. En estos properties estamos definiendo el mecanismo de conexion a la base de datos. Cambiando estos valores por los adecuados podemos conectar a cualquiera otra base de datos que tengamos.

- Existe una ultima propiedad que conviene tener activa en los primeros momentos, cuando estamos desarrollando:

Esta propiedad hace que si el modelo de datos no existe se cree de manera automatica, pero cada vez que invocamos al mecanismo de persistencia, borra el contenido de las tablas y las vuelve a crear si no existen previamente. Esto al comienzo cuando estamos de “pruebas” viene de fabula, despues ya podemos comentar esta opcion para trabajar con datos reales que tengamos insertados.

Tenemos los Entity ya creados. Como puedo por ejemplo, insertar uno de ellos en la base de datos.
Pues con un trozo de codigo similar al siguiente:

- Primero creamos un EntityManager que nos permita manipular y trabajar con los objeto Entity:


String UNIDAD_DE_PERSISTENCIA = "DOCSPU";
EntityManagerFactory factory = Persistence.createEntityManagerFactory(UNIDAD_DE_PERSISTENCIA, System.getProperties());
em = factory.createEntityManager();

Como ves, el nombre que uso es “DOCSPU”, esto es porque asi lo tenemos definido en el fichero “persistence.xml”, asi sabe como recuperar las clases y propiedades que corresponden a esta unidad de persistencia. Si tu cambiaste el nombre en el XML, aqui deberias poner el que hayas usado.

Una vez creada la EntityManager, ya es muy simple, abrir una transaccion e incluso almacenar elementos (Entity) en la base de datos. Un ejemplo para insertar un “Usuario” podria ser:

em.getTransaction().begin();
Usuario u = new Usuario();
u.setId(100);
u.setName("jose");
u.setEmail("notengo@gmail.com");
em.persist(u);
em.flush();
em.getTransaction().commit();

Como observas, hemos recuperado una transaccion (getTransaction), instanciado un objeto usuario, asignado valores a sus atributos, lo hemos “persistido” (almacenado) en la base de datos con “persist” y por ultimo un commit de la transaccion.

Es decir, solo escribiendo una clase, y un XML, ya hemos insertado un usuario con campos nombre y email en una tabla “Usuarios” que se ha generado de manera dinamica. ¿No te parece ideal?.
No hay que escribir metodos, insert, update ni delete, ni crear el modelo de la tabla si no nos interesa. Todo se hace dinamicamente.

Consultas:

Para hacer las consultas en JPA se emplea un lenguaje denominado JPQL, no es SQL exactamente porque trabaja con “objetos” no con “columnas” pero si muy parecido.
Por ejemplo, si la consulta de todos los campos de una tabla es “SELECT * FROM USUARIOS”, en JPQL la consulta seria “SELECT u FROM Usuario u”, Donde “Usuario” no es el nombre de una tabla, sino de la clase “Entity” y “u” son los identificadores del objeto.
Mas ejemplos: “SELECT u.id,u.name FROM Usuario u where u.name LIKE := PARAMETRO”.
Es muy parecido a construir un PreparedStatement donde pasamos los parametros.
Para ejecutar estas consultas empleamos el objeto “Query”. Query admite dos metodos:

- getResultList, cuando el conjunto de valores devuelto es una lista de valores, por ejemplo un SELECT de varios campos.

- getSingleResult, cuando solo se devuelve un unico objeto (fila).

Por ejemplo para obtener Todos los proyectos de una tabla “Proyectos”:

Query q = em.createQuery("SELECT p FROM MdcoreProject p");
List<MdcoreProject> proyectos = q.getResultList();
int num_proyectos = proyectos.size();

Si quisieramos ejecutar consultas con parametros, las variables a sustituir van precedidas de “:” y debemos pasarlas con setParameter. Ejemplo: una consultas de proyecto cuyo proyecto es “666″ seria:

Query q = em.createQuery("SELECT p FROM MdcoreProject p WHERE p.id : = PROYECTO_ID");
q.setParameter("PROYECTO_ID","666");
MdcoreProject mi_proyecto_buscado = (MdcoreProject) q.getSingleResult();

Como veis, estamos trabajando con “objetos” no con clausulas SQL.

¿Y tenemos que tener esas consultas JPQL embebidas en el codigo?

Pues aqui tenemos otra ventaja de JPA, Si no queremos, no tenemos porque. Podemos si queremos definir “anotaciones” con las sentencias SQL en el cuerpo del “Entity”, estas sentencias SQL se indicarian con la anotacion “@NamedQuery”. Un ejemplo:

Fijate en el codigo del Entity, es una clase llamada “MdcoreUser” que implementa los datos de un usuario. Con @Entity ya indicamos que es una entidad. con @Table ya forzamos a que se mapee con una tabla llamada “MDCORE_USER”, en caso de no usar la anotacion @Table, el nombre de la tabla creada se llama exactamente igual al nombre de la clase java.

Con la anotacion @NamedQueries vamos indicando las diferentes sentencias SQL que queremos utilizar, bueno, perdon… sentencias JPQL. Y esto es “fantastico” otra vez, pues al ser anotaciones, podemos cambiarlas sobre “la marcha”. Aqui aprovecho y comento otras anotaciones de las que no habia hablado, ya vimos que con @Id vamos indicando que columnas son clave. Pues bien con @GeneratedValue podemos indicar si queremos que los campos clave se creen de manera automatica, por ejemplo mediante el uso de secuencias. En otro caso, somos nosotros los que debemos calcular el valor de un nuevo id cuando vayamos a insertar. Otra anotacion es @Column nos permite asociar un atributo a un nombre de columna en particular. Por ejemplo tenemos un atributo llamado “fxCreacion” pero en la base de datos la columna se llama “FECHA_CREACION”. En caso de no indicarlo, las columnas de la tabla se llamaran igual que el nombre del atributo del Entity.

En el caso de que queramos usar las anotaciones @NamedQuery, si que cambia un poco la forma de invocar a “Query” que vimos un poco mas arriba. y es que en este caso, en lugar de usar un createQuery(“String con el JPSQL”), debemos usar createNativeQuery(“nombre_de_la_anotacion_namedQuery_definida_en_el_Entity”).

Por ejemplo si tuvieramos:

@NamedQuery(name = "MdcoreUser.findById", query = "SELECT s FROM MdcoreUser " +
"s WHERE s.id = :id")

La consulta podria ser:

Query q = em.createNativeQuery("MdcoreUser.findByID");
q.setParameteR("id","100");
MdcoreUser u = q.getSingleResult();

En este punto tambien comentar que en estos entornos de desarrollo (Eclipse, netbeans) puede hacerse el paso inverso, es decir, a partir de una base de datos, generar el Entity correspondiente. A este proceso se le llama “Ingenieria inversa”. Pero no lo cubriremos en este articulo.
Podeis de todas formas obtener mas informacion en el sitio de Eclipse o en Netbeans. De todas formas, pienso que lo mas comodo es escribirlo uno mismo (ademas el Entity es un simple bean).

Ejemplo CMS:

Como se que esto al principio es complicado, aunque luego se le pilla el truco. Os dejo unos cuantos ficheros fuente con un ejemplo de aplicacion JPA. Solo incluyo los fuentes, para que no pese mucho, los .jar correspondientes a EclipseLink y driver JDBC debeis colgarlos vosotros.

Esta pequeña aplicacion es un interprete de comandos que nos permite insertar documentos en la base de datos en base a tags, por ejemplo podriamos insertar un documento “Introduccion a JPA.pdf” bajo los tags “Programacion,Java,JPA”. Consultar documentos en base a su tag (p.ej devolver todos los documentos almacenados que sean de la categoria: “Oracle”) y descargar documentos.

Usa varias tablas, pero la mas importante es MdcoreDocs. Realmente las demas son solo para un desarrollo a mayor nivel. Las tablas son:

- MdcoreUser, Guarda informacion de los usuarios
- MdcoreProject, Guarda informacion de los proyectos
- MdcoreMetadata, Guarda metadatos del proyecto (p.ej DOCUMENTOS, SCRIPTS…)
- MdcoreTags, Tags de los diferentes docs (Oracle, Java, Bases de datos, MySQL, etc..)
- MdcoreDocs, Los documentos almacenados en la base de datos.
- MdcoreSetDocTags, Permite asociar documentos con tags

Para simplificar no hay relaciones activas entre tablas, y por defecto cuando se inserta un documento en la base de datos, se asigna de manera automatica a un proyecto=0, usuario=1, metadato=1
(el proyecto 0 vendria a ser: DEFECTO).

El interprete de comandos se lanza con la clase MyDocs. Este seria por ejemplo una sesion donde almacenamos un documento en la base de datos:

Y aqui el resultado de insertar en la base de datos (nota que no he creado el modelo de datos, se crea de manera automatica):

Un Blob insertado en MySQL de la manera mas rapida y sencilla posible ^^

Este ha sido un tutorial muy basico, unicamente para que conozcais esta API y tal vez os sirva de ayuda para empezar a mapear vuestros Entity. no creo que siga con los tutoriales, pero con JPA se pueden hacer cosas mas complejas y establecer asociaciones 1 a 1 y 1 a M entre las tablas. Esperemos que Hermoso dia se anime y continue con algun tutorial mas avanzado. (Gracias Lechuck por enseñarme este API).

Como prometi, aqui los fuentes (estan como .pdf realmente son .tar, renombra de .pdf a .tar y descomprimelos, los subo asi, pq wordpress solo dejar subir pdfs e imagenes).

Enlace | Ejemplo de JPA, Codigo fuente
Enlace | Introduccion a JPA, Tutorial de Sun

RationalPlan Project Viewer, Visor de archivos de Microsoft Project

Estas en el trabajo y tu jefe de proyecto te envia por correo un project, y te dice: quiero que tengas esto hecho para el fin de semana. Entonces vas tu y le dices: ah! se siente, uso Linux y no puedo abrir el documento. Pues nene!! se te acabo el chollo.

RationalPlan Project Viewer
es una pequeña aplicacion para Windows, Mac y Linux con el cual podemos visualizar las planificaciones realizadas con Microsoft Project.
No esta mal, pero yo me sigo quedando con OpenProj (que ademas me permite editar el fichero) y que te puedes descargar tambien como paquete .deb.

Enlace | RationalPlan Project Viewer

Escribir nuestras propias Anotaciones en Java

Las anotaciones fueron introducidas en JDK 1.5 y es una forma de añadir informacion (metadatos) al codigo. Podriamos considerarlo como una especie de “comentarios” que añadimos al codigo pero “ojo” no son comentarios realmente, es informacion extra que podemos utilizar en tiempo de ejecucion para por ejemplo ser procesada por un script o generar nuevo codigo adicional.

Si queremos crear nuestras propias anotaciones en Java, es muy sencillo:

- Debemos definir un interface para la anotacion, esto es muy parecido a definir una clase. Por ejemplo un ejemplo (valga la redundancia) de anotacion podria ser la siguiente (sustituyendo class por @interface):

public @interface MisAnotaciones {
int id();
String comentario();
}

Y ya podriamos usarla en nuestro codigo. Por ejemplo al principio de la clase:

@MisAnotaciones
(
id=3, comentario="Esto es un comentario"
)
public class Test {
.....
}

¿Sencillo eh?. ¿Y si queremos acceder a las anotaciones en tiempo de ejecucion?.
Pues facil tambien, empleariamos el API de reflection y el metodo getAnnotations.
Aqui os voy a dejar un ejemplo completo y sencillo, donde podeis ver como definir unas anotaciones, y acceder a ellas desde una clase o un metodo:

Fichero “MisAnotaciones.java” donde definimos 2 interfaces de anotaciones, una llamada “MisAnotaciones” y otra llamada “Otra” (nada como ser original ^^):

import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@interface Otra {
String description();
}
@Retention(RetentionPolicy.RUNTIME)
public @interface MisAnotaciones {
int id();
String comentario();
}

Fichero "Test.java"con el ejemplo de la clase sobre la que escribimos las anotaciones:

@MisAnotaciones
(
id=3, comentario="Esto es un comentario"
)
@Otra
(
description="Otra anotacion"
)
public class Test {

	@Otra
	(
	description="Anotacion en mi metodo"
	)
	public void mimetodo()
	{}

}

Y aqui ya el codigo de ejemplo, donde recuperamos y examinamos las anotaciones de la clase principal:

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;

public class Test2 {

	public static void main(String[] args) {

		// En tiempo de ejecucion
		try {

			Test t = new Test();
			// referencia a la  clase
			Class c = t.getClass();
			// recuperamos las anotaciones de la clase mediante reflection
			Annotation[] anotaciones = c.getAnnotations();
			int num = anotaciones.length;
			System.out.printf("La clase tiene %s Anotaciones\r\n ", num);
			for (int i = 0; i &lt; num; i++) {
				System.out
						.println("\tAnnotation " + i + ": " + anotaciones[i]
								+ ", type="
								+ anotaciones[i].annotationType().getName());
			}

			// leemos la primera anotacion de la clase
			MisAnotaciones a = (MisAnotaciones) anotaciones[0];

			String comentario = a.comentario();
			System.out.println("Comentario de la anotacion @MisAnotaciones es:"
					+ comentario);

			// recuperamos ahora las anotaciones del metodo
			Method m = c.getMethod("mimetodo");
			anotaciones = m.getAnnotations();

			num = anotaciones.length;

			System.out.printf("El metodo tiene %s anotaciones\r\n", num);

			for (int i = 0; i &lt; num; i++) {
				System.out
						.println("\tAnnotation " + i + ": " + anotaciones[i]
								+ ", type="
								+ anotaciones[i].annotationType().getName());
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

Mas informacion | getAnnotations | Java Passion

Resident Evil degeneration

Pronto podremos ver la primera pelicula de animacion basada en el universo de Resident Evil, que lleva por titulo “Resident Evil degeneration”. Por cierto, ya hay tambien rumores acerca de una cuarta parte.

Enlace | Resident Evil Degeneration

El “arte” del codigo

¿Quien dice que el codigo son solo secuencias de caracteres (y muchas veces sin sentido)?.
Desde el punto de vista adecuado, “el codigo es arte”.

Enlace | Mangas Verdes

Pidgin 2.5.2 Disponible

Podemos descargarlo desde GetDeb, no olvideis de eliminar el paquete anterior antes de instalarlo.

ShipIt, Pide tu CD de Ubuntu 8.10 Intrepid Ibex

Ya podemos solicitar nuestro CD de Ubuntu 8.10 Intrepid Ibex, el cual mediante el servicio de ShipIt sera enviado gratuitamente a nuestro domicilio.
El mensaje del sitio es que Ubuntu 8.10 no ha sido liberado todavia, pero que guardaran nuestra peticion en sus bases de datos para atenderla cuando sea posible. Para poder solicitar el CD debes tener cuenta en Launchpad. Una vez que comiencen los envios, este puede tardar entre seis y diez semanas.

* CD Ubuntu: https://shipit.ubuntu.com

* CD Kubuntu: https://shipit.kubuntu.org

* CD Edubuntu: https://shipit.edubuntu.org

Oracle SQL Developer Data Modeling, Crear Modelos E/R de Bases de datos Oracle

SQL Developer es una muy buena herramienta para trabajar con bases de datos Oracle, pero carecia de una funcion muy importante: la de diseñar o modelar diagramas Entidad/Relacion de nuestras bases de datos.
Esto ahora se ha solucionado con una nueva tool llamada “SQL Developer Data Modeling” que se encuentra actualmente en fase de testeo y que podemos descargarnos desde el sitio de Oracle.

Llevo muy poco tiempo usandola, asi que desconozco si existe una opcion para generar el modelo de una base de datos ya existente mediante ingenieria inversa, el modo en que yo he hecho esto has sido a partir de script DDL (lenguaje de definicion de datos) SQL que puedes generar desde SQLdeveloper cuando seleccionar uno o mas tablas (click derecho > Export DDL > Save to File…) e importando este fichero .sql desde SQL Developer Data Modeling (File > Import DDL File).

La ejecucion de SQL Developer Data Modeling es simple, te descargas el .zip correspondiente, lo descomprimes y luego desde el directorio correspondiente ejecutas.

$ cd /osdm/bin
$ ./osdm.sh &

Descarga | Oracle (requiere registro)



The next version of Ubuntu is coming soon


¿Es compatible tu equipo con Ubuntu?


( Muchos fondos de pantalla, aqui )

DESCARGATE SCIFI LIFE

365 Dias de Soledad
Me debes los sueños, las promesas y las noches rotas. Me debes la paz, la sonrisa y la esperanza robadas. Me debes la sangre, las lágrimas y el sudor vertido. Me debes las noches vacías, los abrazos anhelados. Me debes un beso de ajenjo de tu amarga boca.

The Ubuntu Counter Project - user number # 11961
Geo Visitors Map
octubre 2008
L M X J V S D
« sep   nov »
 12345
6789101112
13141516171819
20212223242526
2728293031  

Blog Stats

  • 26,170,951 hits

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 1.013 seguidores