2º DAM - Desarrollo de Aplicaciones Multiplataforma.
Acceso a Datos
BASES DE DATOS ORIENTADAS A OBJETOS -
NEODATIS.
Las bases de datos orientadas a objetos (BDOO u OOBD en inglés) son bases de datos
que almacenan objetos directamente en su estructura, conservando tanto la estructura de
los datos como las funciones existentes y las relaciones entre los objetos.
La ventaja más evidente de las BDOO es la integración directa de la estructura de datos con
el sistema.
Para probar las BDOO trabajaremos con Neodatis.
NEODATIS
Neodatis ODB es una base de datos orientada a objetos con licencia GNU muy simple
que actualmente es compatible con los lenguajes Java, .Net, Google Android, Groovy
y Scala.
Con Neodatis podemos evitar la falta de impedancia entre los mundos orientados a
objetos y los relacionales, ya que actúa como una capa de persistencia transparente
para Java, .Net y Mono.
Neodatis ODB soporta consultas nativas, es decir, podemos lanzar una consulta
directamente desde Java, por ejemplo.
Además es bastante simple e intuitivo. Los objetos pueden ser añadidos fácilmente a la
base de datos, lo que requiere clases no repetitivas y que las clases ya existentes no
puedan modificarse.
También cuenta con un explorador ODB, una herramienta gráfica para navegar,
consultar, actualizar y borrar objetos, así como la importación / exportación de bases de
datos desde y hacía archivos XML.
Sintaxis
La sintaxis para trabajar con Neodatis va a ser vista en Java.
Lo primero, se debe tener en cuenta que es muy importante que después de haber
abierto una conexión a la base de datos y realizar las operaciones que deseemos,
cerremos dicha conexión, si no, nos fallará en futuras ocasiones.
Conexión / Desconexión
La conexión se realiza con un objeto de clase ODB, en la que indicaremos la ruta donde
se encuentra nuestra base de datos. Esto servirá tanto para abrirla como para crear una
nueva, en caso de que en la ruta indicada aún no exista ninguna. En este caso, vamos
a generar una nueva en la ruta D:\ y se llamará [Link].
ODB odb = ODBFactory.open("d:\\[Link]");
Y para cerrar la conexión, simplemente se indica que queremos cerrar el objeto ODB
creado.
odb.close();
Inserción de objetos
No es necesario definir en la base de datos como queremos guardar los objetos, éstos
lo harán automáticamente, creándose las “tablas” respecto a las clases que vayamos
almacenando. Lo que sí se debe tener creada es una clase en Java que indique las
propiedades y métodos a guardar en la base de datos. Es decir, si queremos almacenar
un registro de jugadores de varios deportes, deberemos crear una clase Jugadores, con
sus propiedades, métodos, getters y setters correspondientes. Tal que así, por ejemplo.
(NOTA: La clase debe estar en el mismo paquete que el fichero donde vamos a realizar
las pruebas).
public class Jugadores {
// Propiedades
private String nombre;
private String deporte;
private String ciudad;
private int edad;
// Constructores
public Jugadores(){};
public Jugadores(String nombre, String deporte, String ciudad, int
edad) {
super();
this.nombre = nombre;
this.deporte = deporte;
this.ciudad = ciudad;
this.edad = edad;
}
// Métodos
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDeporte() {
return deporte;
}
public void setDeporte(String deporte) {
this.deporte = deporte;
}
public String getCiudad() {
return ciudad;
}
public void setCiudad(String ciudad) {
this.ciudad = ciudad;
}
public int getEdad() {
return edad;
}
public void setEdad(int edad) {
this.edad = edad;
}
/ Fin clase Jugadores
} /
Creada la clase, la siguiente fase es generar los objetos Jugadores que queramos
almacenar en la BD e insertarlos. Tambíen bastante intuitivo.
// Creo los jugadores
Jugadores j1= new Jugadores ("María", "voleibol", "Madrid", 14);
Jugadores j2= new Jugadores ("Miguel", "tenis", "Madrid", 15);
Jugadores j3= new Jugadores ("Mario", "baloncesto", "Guadalajara", 15);
Jugadores j4= new Jugadores ("Alicia", "tenis", "Madrid", 14);
// Inserto los objetos
odb.store(j1);
odb.store(j2);
odb.store(j3);
odb.store(j4);
Y listo. Neodatis detectará que tipo de objeto son y los insertará en una u otra “tabla”.
Mostrar datos
Para mostrar los datos crearemos un conjunto de objetos genéricos parametrizado al
tipo de objeto que queremos traernos. En este caso, Objects<Jugadores>. En él se
cargarán todos los objetos del tipo Jugadores que nos traeremos desde la base de
datos.
Posteriormente recorreremos el conjunto hasta el final y accederemos a las propiedades
que queramos imprimir con los getters anteriormente configurados.
// Genero un conjunto de objetos y los traigo del ODB conectado
Objects<Jugadores> objects=odb.getObjects(Jugadores.class);
// Imprimo cuantos objetos me he traido de la BD
System.out.println(objects.size() + " jugadores:");
int i = 1; // Meramente estético. Así muestra listados los objetos
// Mientras haya objetos, los capturo y muestro
while(objects.hasNext()){
// Creo un objeto Jugadores y almaceno ahí el objeto
Jugadores jug= objects.next();
// Imprimo las propiedades que me interes de ese objeto
System.out.println((i++) + "\t: " + jug.getNombre() + "*" +
jug.getDeporte() + "*" + jug.getCiudad() + "*" + jug.getEdad());
} // Fin del While
Consultas
Claro, puede darse el caso de que no queramos listar todos los objetos de un tipo
determinado, sino que queramos sólo los que tengan X propiedad o cumplan tal
condición.
Para ello deberemos crear un objeto IQuery, que a su vez será un objeto
CriteriaQuery, donde recibirá dos parámetros. El primero será el tipo de objeto que
queramos consultar, y el segundo la condición impuesta. Un Where en toda regla,
básicamente.
Hecho esto, nos traeremos todos los objetos igual que en ejemplo anterior, pero
pasando como parámetro del ODB nuestra consulta. Y ya imprimiríamos los resultados
como vimos en el anterior punto.
Veamos un ejemplo
/* Genero la consulta. Llamo a la clase Jugadores
* La condición será que la propiedad deporte sea igual a tenis
*/
IQuery query = new CriteriaQuery(Jugadores.class, Where.equal("deporte",
"tenis"));
// Y ordeno el resultado por nombre y edad
query.orderByDesc("nombre,edad");
// Cargo los objetos pasando como parámetro del odb nuestra consulta
Objects<Jugadores> objects = odb.getObjects(query);
También podemos separar este proceso un poco más, por si nos resulta más claro verlo
de otra forma. El único cambio que haremos será crear un objeto ICriterion donde
realizaremos la consulta, y pasaremos ese objeto como segundo parámetro de nuestro
objeto CriteriaQuery. Tal que así.
// Realizo la condición sobre la propiedad edad
"edad",14);
ICriterion criterio = Where.equal(
/* Creo el objeto para realizar la consulta y mando el ICriterion
* como segundo parámetro
*/
CriteriaQuery query = new CriteriaQuery(Jugadores.class, criterio);
// Y cargo todo en un objeto, como siempre
Objects<Jugadores> objects = odb.getObjects(query);
Y tenemos varias formas de lanzar un where. Por ejemplo:
// Jugadores que empiezan por M
ICriterion criterio2 = Where.like("nombre","M%");
// Jugadores mayores de 14
// [Link] --> mayor o igual, [Link] --> menor que, [Link] ---> menor o
igual
// [Link] --> Distinto
//[Link]("atributo") si un atributo es nulo
//[Link]("atributo") si un atributo es nulo
ICriterion criterio3 = Where.gt( "edad",14);
Haremos un inciso para aclarar la consulta anterior. [Link] es para indicar “mayor
que”. También podemos usar :
● [Link] -> mayor que
● [Link] -> mayor o igual
● [Link] -> menor que
● [Link] -> menor o igual
● [Link] -> Distinto a
● [Link](“atributo”) si un atributo es nulo
● [Link](“atributo”) si un atributo es no nulo
// Jugadores que no empiezan por M
Where.like("nombre","M%"));
ICriterion criterio4 = Where.not(
// Jugadores de 15 años de Madrid
"ciudad",
ICriterion criterio = new And().add(Where.equal(
"Madrid")).add(Where.equal( "edad",15));
// Jugadores >= de 15 años y de Madrid
"ciudad",
ICriterion criterio2 = new And().add(Where.equal(
"Madrid")).add(Where.ge("edad",15));
Y también podemos realizar consultas complejas, todo lo que queramos complicarnos
es posible. Las pasaremos brevemente porque esto es una aproximación.
Por ejemplo, veamos las siguientes:
// Suma de edades
Values val = odb.getValues(new
ValuesCriteriaQuery(Jugadores.class).sum("edad"));
ObjectValues ov= val.nextValues();
BigDecimal value = (BigDecimal)ov.getByAlias("edad");
// también valdría BigDecimal value = (BigDecimal)[Link](0);
// Cuenta de jugadores
Values val2 = odb.getValues(new
ValuesCriteriaQuery(Jugadores.class).count("nombre"));
ObjectValues ov2= val2.nextValues();
BigInteger value2 = (BigInteger)ov2.getByAlias("nombre");
// Media de edades
Values val3 = odb.getValues(new
ValuesCriteriaQuery(Jugadores.class).avg("edad"));
ObjectValues ov3= val3.nextValues();
BigDecimal value3 = (BigDecimal)ov3.getByAlias("edad");
// Edad máxima y mínima
Values val4 = odb.getValues(((ValuesCriteriaQuery) new
ValuesCriteriaQuery(Jugadores.class.max("edad",
"edad_max")).min("edad","edad_min"));
ObjectValues ov4= val4.nextValues();
BigDecimal maxima = (BigDecimal)ov4.getByAlias("edad_max");
BigDecimal minima = (BigDecimal)ov4.getByAlias("edad_min");
Borrado de objetos
Para borrar un objeto crearemos un objeto IQuery para traernos a memoria los objetos
a borrar. Nos posicionamos en el primero objeto y lo borramos usando el ODB.
// Hacemos la consulta para borrar a María
IQuery query = new CriteriaQuery(Jugadores.class, Where.equal("nombre",
"María"));
// Nos posicionamos en el primer resultado
Jugadores jug=(Jugadores) odb.getObjects(query).getFirst();
// Y lo borramos
odb.delete(jug);
Si quisiéramos borrar más de un objeto, optaríamos por una estructura como la siguiente:
// Hacemos la consulta para borrar a todos los jugadores de edad 15
IQuery query = new CriteriaQuery([Link], [Link]("edad", 15));
// Cargamos los objetos que coincidan con esa consulta
Objects<Jugadores> objects = [Link](query);
while ([Link]()){
Jugadores jug= [Link]();
// Y lo borramos
[Link](jug);
}
Modificación de objetos
Como viene siendo habitual, creamos un IQuery con los objetos que queramos
modificar, cargaremos el objeto en la clase Jugadores de Java, le cambiaremos la
propiedad que deseemos usando los setters que programamos al principio y
volveremos a almacenar el objeto en la base de datos.
IQuery query = new CriteriaQuery(Jugadores.class, Where.equal("nombre",
"María"));
// A María le ponemos Ciclismo como deporte
Jugadores jug=(Jugadores) odb.getObjects(query).getFirst();
jug.setDeporte("Ciclismo");
odb.store(jug);
Instalación y configuración
La instalación de NeoDatis es un proceso bastante intuitivo de realizar. Simplemente
nos descargamos el paquete NeoDatis ODB de la siguiente dirección:
[Link]
Y descomprimimos el paquete. Nos encontraremos con lo siguiente:
De esta descarga nos interesan dos archivos. Neodatis-odb-[Link].jar, que será la
librería para nuestro proyecto en Java, y odb-explorer, para usar el explorador de base
de datos. .bat si usamos Windows, .sh para Linux.
Generamos un nuevo proyecto Java, y crearemos (en caso de que no esté creada) una
nueva carpeta, llamada lib, dentro de éste. Aquí copiaremos el .jar de NeoDatis.
Nos iremos a Propiedades del proyecto -> Java Build Path -> Libraries y elegiremos
Add JAR, desde donde añadiremos el .jar de la ruta nombreProyecto/lib que hemos
creado.
Y esa es toda la configuración previa que debemos tener. Naturalmente, ahora toca
crear la estructura de clases para leer / insertar / modificar / borrar elementos de nuestra
base de datos, tal y como explicamos en la sección anterior.
Y listo, ya podemos trabajar con NeoDatis ODB .