Spring Data y Mongo DB en un proyecto Real

Preview:

DESCRIPTION

Presentación que utilicé en el Spring IO 2012 para la charla "Spring Data y Mongo DB en un proyecto Real".

Citation preview

David Gómez@dgomezg

Spring Data y MongoDBen un proyecto real.

sábado 18 de febrero de 12

Spring CORE

Rich Web Applications

with Spring

Enterprise Integration

sábado 18 de febrero de 12

#springio

#extrema

sábado 18 de febrero de 12

Hablaremos de

Un caso real

¿Por qué NoSQL? ¿Por qué MongoDB?

MongoDB ‘a pelo’

Spring Data al rescate

¡Cuidado!

sábado 18 de febrero de 12

Un caso real. Control de tráfico marítimo

sábado 18 de febrero de 12

Emisor AIX

3-5 min

sábado 18 de febrero de 12

Emisor AIX

3-5 min

sábado 18 de febrero de 12

Emisor AIX

3-5 min

Receptor GPS

Goniometro

Estación Meteo,

Cámaras,

...

Radar (3 s)

sábado 18 de febrero de 12

El problema: La escalabilidad

sábado 18 de febrero de 12

El problema: La escalabilidad

Por cada barco:

Recepción y procesamiento de señales (nº)

Transacciones,

Cálculo de alarmas

Gestión de Históricos

sábado 18 de febrero de 12

El problema: La escalabilidadSeñales

(1 AIS x 3 min + 1 radar x 3 seg) x 100 barcos

Alarmas

Persistencia de Líneas de Varada

(10.000+ ptos x 100+ líneas)

40 Alarmas

Zonas, Elementos Navegación

Persistencia: Total: 87 tablas + históricos(x2)

sábado 18 de febrero de 12

El problema: La escalabilidad

sábado 18 de febrero de 12

¿Por qué NoSQL?

Teorema CAP (Eric Brewer)

Source: Nathan Hurst’s Blog

sábado 18 de febrero de 12

¿Por qué NoSQL?

Teorema CAP (Eric Brewer)

CConsistency

Source: Nathan Hurst’s Blog

sábado 18 de febrero de 12

¿Por qué NoSQL?

Teorema CAP (Eric Brewer)

C AConsistency Availability

Source: Nathan Hurst’s Blog

sábado 18 de febrero de 12

¿Por qué NoSQL?

Teorema CAP (Eric Brewer)

C A

P

Consistency Availability

Partition Tolerance

Source: Nathan Hurst’s Blog

sábado 18 de febrero de 12

¿Por qué NoSQL?

Teorema CAP (Eric Brewer)

C A

P

Consistency Availability

Partition Tolerance

Source: Nathan Hurst’s Blog

sábado 18 de febrero de 12

¿Por qué NoSQL?

Teorema CAP (Eric Brewer)

C A

P

Consistency Availability

Partition Tolerance

Sólo 2

Source: Nathan Hurst’s Blog

sábado 18 de febrero de 12

¿Por qué NoSQL?

Teorema CAP (Eric Brewer)

C A

P

Consistency Availability

Partition Tolerance

Sólo 2

Oracle, MySQL,

Source: Nathan Hurst’s Blog

sábado 18 de febrero de 12

¿Por qué NoSQL?

Teorema CAP (Eric Brewer)

C A

P

Consistency Availability

Partition Tolerance

Sólo 2

Oracle, MySQL,

MongoDB, DataStore,

HyperTable, HBase

Redis, Mem

cacheDB

Source: Nathan Hurst’s Blog

sábado 18 de febrero de 12

¿Por qué NoSQL?

Teorema CAP (Eric Brewer)

C A

P

Consistency Availability

Partition Tolerance

Sólo 2

Oracle, MySQL,

MongoDB, DataStore,

HyperTable, HBase

Redis, Mem

cacheDBDyn

amo, V

oldem

ort,

Cas

sand

ra,

Simple

DB, Cou

chDB,

RiaK

RDBMSOrientadas a documento

orientadas a columnaKey-Value

Source: Nathan Hurst’s Blog

sábado 18 de febrero de 12

Pero... ¿NoSQL?

(cc) Photo by mwin - http://www.flickr.com/photos/wingler/3429634150

sábado 18 de febrero de 12

Pero... ¿NoSQL?

(cc) Photo by mwin - http://www.flickr.com/photos/wingler/3429634150

sábado 18 de febrero de 12

Pero... ¿NoSQL?

(cc) Photo by mwin - http://www.flickr.com/photos/wingler/3429634150

NoSQL !== no SQL

Not only SQL

sábado 18 de febrero de 12

NoSQL: ACID vs BASE

Atomicity,

Consistency,

Isolation,

Durability

(cc) Photo by zhouxuan12345678 - http://www.flickr.com/photos/53921113@N02/5645102295/

Basically Available,

Soft state,

Eventual consistency

sábado 18 de febrero de 12

orientadas a Columna orientadas a Documento

orientadas a GrafosKey-value

Tipos.

sábado 18 de febrero de 12

¿Por qué MongoDB?

Orientada a documento

Almacenados en Colecciones

(bajo una clave)

Los documentos pueden ser heterogéneos

Formatos textuales: JSON & BSON

(cc) Photo by Ampersand Duck - http://www.flickr.com/photos/ampersandduck/4941185476

sábado 18 de febrero de 12

MongoDB

Escrita en C++

Orientada a documento

Formato JSON (o BSON)

Un poco SQL (queries, índices, Referencias externas)

Particionado horizontal (sharding)

Consultas Javascript

(cc) Photo by Ampersand Duck - http://www.flickr.com/photos/ampersandduck/4941185476

sábado 18 de febrero de 12

Orientadas a Documento

Documentos formateados en JSON

sábado 18 de febrero de 12

Orientadas a Documento

Documentos formateados en JSON

{ "_id" : "224000999", "_class" : "com.vts.model.Vessel", "flag" : "ALBANIA", "name" : "Sample NOT_AVAILABLE Vessel 224000999", "callsign" : "SV224000999", "toBow" : 25, "toStern" : 5, "toPort" : 5, "toStarboard" : 5, "comments" : "Sample vessel created automatically for test purposes"}

sábado 18 de febrero de 12

El API

Consola y API JavaScript:

sábado 18 de febrero de 12

El API

Consola y API JavaScript:beleriand:bin dgomez$ ./mongoMongoDB shell version: 1.8.1connecting to: test>

sábado 18 de febrero de 12

El API

Consola y API JavaScript:beleriand:bin dgomez$ ./mongoMongoDB shell version: 1.8.1connecting to: test> > use vtsswitched to db vts>

sábado 18 de febrero de 12

El API

Consola y API JavaScript:beleriand:bin dgomez$ ./mongoMongoDB shell version: 1.8.1connecting to: test> > use vtsswitched to db vts>> show collectionsEventWeatherDatasystem.indexesvessel>

sábado 18 de febrero de 12

El API

Consola y API JavaScript:beleriand:bin dgomez$ ./mongoMongoDB shell version: 1.8.1connecting to: test> > use vtsswitched to db vts>> show collectionsEventWeatherDatasystem.indexesvessel>> db.Event.find(){ "_id" : ObjectId("4e0b5b211446446f6be3bb1a"), "_class" : "com.vts.model.events.SystemEvent", "timestamp" : ISODate("2011-06-29T17:04:33.039Z") }{ "_id" : ObjectId("4e0b5b3d144676f49946443f"), "_class" : "com.vts.model.events.SystemEvent", "timestamp" : ISODate("2011-06-29T17:05:01.394Z") }>

sábado 18 de febrero de 12

El API

Consola y API JavaScript:

sábado 18 de febrero de 12

El API

Consola y API JavaScript:> show collectionsEventWeatherDatasystem.indexesvessel>

sábado 18 de febrero de 12

El API

Consola y API JavaScript:> show collectionsEventWeatherDatasystem.indexesvessel> > db.alarms.save({"type" : "speed", "severity" : "warn", "vesselSSID" : "224000999"})>

sábado 18 de febrero de 12

El API

Consola y API JavaScript:> show collectionsEventWeatherDatasystem.indexesvessel> > db.alarms.save({"type" : "speed", "severity" : "warn", "vesselSSID" : "224000999"})>> show collectionsEventWeatherDataalarmssystem.indexesvessel>

sábado 18 de febrero de 12

El API

Consola y API JavaScript:> show collectionsEventWeatherDatasystem.indexesvessel> > db.alarms.save({"type" : "speed", "severity" : "warn", "vesselSSID" : "224000999"})>> show collectionsEventWeatherDataalarmssystem.indexesvessel>> db.alarms.find(){ "_id" : ObjectId("4f3acca3ed4cc8078fd1a4be"), "type" : "speed", "severity" : "warn", "vesselSSID" : "224000999" }>

sábado 18 de febrero de 12

Documentos

Identificados por un “_id” (generado o asignado)

Textual (JSON)

Binario (BSON)*

Documentos grandes divididos en chunks

sábado 18 de febrero de 12

Programación de clientes

Multitud de lenguajes (drivers)

Transformación a JSON realizada por el driver

sábado 18 de febrero de 12

{ "_id" : "224000999", "flag" : "ALBANIA", "name" : "Sample NOT_AVAILABLE Vessel 224000999", "callsign" : "SV224000999", "toBow" : 25, "toStern" : 5, "toPort" : 5, "toStarboard" : 5, "comments" : "Sample vessel created automatically for test purposes" }

sample.py

Programación de clientes

Multitud de lenguajes (drivers)

Transformación a JSON realizada por el driver

sábado 18 de febrero de 12

{ "_id" : "224000999", "flag" : "ALBANIA", "name" : "Sample NOT_AVAILABLE Vessel 224000999", "callsign" : "SV224000999", "toBow" : 25, "toStern" : 5, "toPort" : 5, "toStarboard" : 5, "comments" : "Sample vessel created automatically for test purposes" }

sample.py

Programación de clientes

Multitud de lenguajes (drivers)

Transformación a JSON realizada por el driver

{ "_id" => "224000999", "flag" => "ALBANIA", "name" => "Sample NOT_AVAILABLE Vessel 224000999", "callsign" => "SV224000999", "toBow" => 25, "toStern" => 5, "toPort" => 5, "toStarboard" => 5, "comments" => "Sample vessel created automatically for test purposes" }

Ruby

sábado 18 de febrero de 12

{ "_id" : "224000999", "flag" : "ALBANIA", "name" : "Sample NOT_AVAILABLE Vessel 224000999", "callsign" : "SV224000999", "toBow" : 25, "toStern" : 5, "toPort" : 5, "toStarboard" : 5, "comments" : "Sample vessel created automatically for test purposes" }

sample.py

Programación de clientes

Multitud de lenguajes (drivers)

Transformación a JSON realizada por el driver

{ "_id" => "224000999", "flag" => "ALBANIA", "name" => "Sample NOT_AVAILABLE Vessel 224000999", "callsign" => "SV224000999", "toBow" => 25, "toStern" => 5, "toPort" => 5, "toStarboard" => 5, "comments" => "Sample vessel created automatically for test purposes" }

Ruby

array( "_id" => "224000999", "flag" => "ALBANIA", "name" => "Sample NOT_AVAILABLE Vessel 224000999", "callsign" => "SV224000999", "toBow" => 25, "toStern" => 5, "toPort" => 5, "toStarboard" => 5, "comments" => "Sample vessel created automatically for test purposes"}

sample.php

sábado 18 de febrero de 12

{ "_id" : "224000999", "flag" : "ALBANIA", "name" : "Sample NOT_AVAILABLE Vessel 224000999", "callsign" : "SV224000999", "toBow" : 25, "toStern" : 5, "toPort" : 5, "toStarboard" : 5, "comments" : "Sample vessel created automatically for test purposes" }

sample.py

Programación de clientes

Multitud de lenguajes (drivers)

Transformación a JSON realizada por el driver

{ "_id" => "224000999", "flag" => "ALBANIA", "name" => "Sample NOT_AVAILABLE Vessel 224000999", "callsign" => "SV224000999", "toBow" => 25, "toStern" => 5, "toPort" => 5, "toStarboard" => 5, "comments" => "Sample vessel created automatically for test purposes" }

Ruby

array( "_id" => "224000999", "flag" => "ALBANIA", "name" => "Sample NOT_AVAILABLE Vessel 224000999", "callsign" => "SV224000999", "toBow" => 25, "toStern" => 5, "toPort" => 5, "toStarboard" => 5, "comments" => "Sample vessel created automatically for test purposes"}

sample.php

BasicDBObject doc = new BasicDBObject(); doc.put("flag", vessel.getFlag()); doc.put("name", vessel.getName()); doc.put("callsign", vessel.getCalSign()); doc.put("toBow", vessel.getBow()); doc.put("toPort", vessel.getStern()); doc.put("toStern", vessel.getPort()); doc.put("toStartboard", vessel.getStarboard()); doc.put("comments", vessel.getComments());

sample.java

sábado 18 de febrero de 12

Cliente Java con MongoDB

‘a pelo’

sábado 18 de febrero de 12

1. Obtener el Driver

Importar el driver

sábado 18 de febrero de 12

1. Obtener el Driver

Importar el driver

<dependency><groupId>org.mongodb</groupId><artifactId>mongo-java-driver</artifactId><version>2.7.0-rc1</version>

</dependency>

sábado 18 de febrero de 12

2. Conexión

Obtener la referencia a la BD y la conexión

sábado 18 de febrero de 12

2. Conexión

Obtener la referencia a la BD y la conexión

Mongo m = new Mongo( "127.0.0.1" , 27017 ); DB db = m.getDB( "playground" );

sábado 18 de febrero de 12

3. Inserciones

Crear e insertar un objeto

sábado 18 de febrero de 12

3. Inserciones

Crear e insertar un objeto

BasicDBObject doc = new BasicDBObject(); doc.put("flag", vessel.getFlag()); doc.put("name", vessel.getName()); doc.put("callsign", vessel.getCalSign()); doc.put("toBow", vessel.getBow()); doc.put("toPort", vessel.getStern()); doc.put("toStern", vessel.getPort()); doc.put("toStartboard", vessel.getStarboard()); doc.put("comments", vessel.getComments());

DBCollection coll = db.getCollection("vessel"); coll.insert(doc);

sábado 18 de febrero de 12

4. Consultas (I)

Obtener todos los documentos de una colección

sábado 18 de febrero de 12

DBCollection vessels = db.getCollection("vessel");

DBCursor cursor = vessels.find(); List<Vessel> vessels = new ArrayList<>();while (cursor.hasNext()) { DBObject jsonVessel = cursor.next(); Vessel vessel = new Vessel(); vessel.setMmsi(jsonVessel.get(“mmsi”)); vessel.setLength(jsonVessel.get(“length”));

// ...

vessels.add(vessel);}

4. Consultas (I)

Obtener todos los documentos de una colección

sábado 18 de febrero de 12

DBCollection vessels = db.getCollection("vessel");

DBCursor cursor = vessels.find(); List<Vessel> vessels = new ArrayList<>();while (cursor.hasNext()) { DBObject jsonVessel = cursor.next(); Vessel vessel = new Vessel(); vessel.setMmsi(jsonVessel.get(“mmsi”)); vessel.setLength(jsonVessel.get(“length”));

// ...

vessels.add(vessel);}

4. Consultas (I)

Obtener todos los documentos de una colección

public abstract class DBCollection {

public final DBCursor find(){ public final DBCursor find( DBObject ref ) public final DBCursor find( DBObject ref , DBObject keys )

public final DBObject findOne( Object obj ) public final DBObject findOne( Object obj, DBObject fields )

public DBObject findAndModify( DBObject query , DBObject update )

}

sábado 18 de febrero de 12

4. Consultas (II)

Consultas “SQL-like”

sábado 18 de febrero de 12

4. Consultas (II)

Consultas “SQL-like” En RDBMS: SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;

Las consultas se hacen también en JSON

sábado 18 de febrero de 12

4. Consultas (II)

Consultas “SQL-like” En RDBMS: SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;

{ “flag” : “ALBANIA” }

Las consultas se hacen también en JSON

sábado 18 de febrero de 12

4. Consultas (II)

Consultas “SQL-like” En RDBMS: SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;

{ “flag” : “ALBANIA” }

Las consultas se hacen también en JSON

beleriand:bin dgomez$ ./mongoMongoDB shell version: 1.8.1connecting to: test> use vtsswitched to db vts> db.vessel.find( { "flag" : "ALBANIA" });{ "_id" : "224312999", "_class" : "com.vts.model.Vessel", "flag" : "ALBANIA", "name" : "Sample TOWING Vessel 224312999", "callsign" : "SV224312999", “length”: 30, “beam” : “10”, "toBow" : 25, "toStern" : 5, "toPort" : 5, "toStarboard" : 5, "comments" : "Sample vessel created automatically for test purposes" }>

sábado 18 de febrero de 12

4. Consultas (II)

Consultas “SQL-like” En RDBMS: SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;

{ “flag” : “ALBANIA” }

Las consultas se hacen también en JSON

beleriand:bin dgomez$ ./mongoMongoDB shell version: 1.8.1connecting to: test> use vtsswitched to db vts> db.vessel.find( { "flag" : "ALBANIA" });{ "_id" : "224312999", "_class" : "com.vts.model.Vessel", "flag" : "ALBANIA", "name" : "Sample TOWING Vessel 224312999", "callsign" : "SV224312999", “length”: 30, “beam” : “10”, "toBow" : 25, "toStern" : 5, "toPort" : 5, "toStarboard" : 5, "comments" : "Sample vessel created automatically for test purposes" }>

DBObject query = new BasicDBObject();query.put("flag", "ALBANIA"); DBCursor albanianShips = vessels.find(query);while (albanianShips.hasNext()) { // ...}

sábado 18 de febrero de 12

Operadores de consulta

Otros operadores

sábado 18 de febrero de 12

Operadores de consulta

Otros operadores

$all$and$exists$gt$in$lt$mod$ne$nin$nor$or$size$type

sábado 18 de febrero de 12

Consultas complejasConcatenación de consultas

RDBMS:

sábado 18 de febrero de 12

Consultas complejasConcatenación de consultas

SELECT * FROM VESSELS WHERE length < 90 AND length > 30AND (flag = “ALBANIA” or flag = ”SAN MARINO”);RDBMS:

sábado 18 de febrero de 12

Consultas complejasConcatenación de consultas

SELECT * FROM VESSELS WHERE length < 90 AND length > 30AND (flag = “ALBANIA” or flag = ”SAN MARINO”);

{ “length” : { $lt : 90, $gt : 30}, $or : [ { “flag” : “ALBANIA”}, { “flag” : “SAN MARINO”} ]}

RDBMS:

Mongo:

sábado 18 de febrero de 12

Consultas complejasConcatenación de consultas

SELECT * FROM VESSELS WHERE length < 90 AND length > 30AND (flag = “ALBANIA” or flag = ”SAN MARINO”);

{ “length” : { $lt : 90, $gt : 30}, $or : [ { “flag” : “ALBANIA”}, { “flag” : “SAN MARINO”} ]}

DBObject query = new BasicDBObject();DBObject condition = new BasicDBObject("$lt",90);condition.put("$gt",30);query.put("length", condition);

DBObject [] flags = {new BasicDBObject("flag", "ALBANIA"), new BasicDBObject("flag", "SAN MARINO")

};query.put("$or", flags);

talks.find(query);

RDBMS:

Mongo:

Mongo

Driver:

sábado 18 de febrero de 12

DBObjects desde JSON

com.mongo.util.JSON

sábado 18 de febrero de 12

DBObjects desde JSON

Object query = JSON.parse("{ 'length' : { $lt : 90, $gt : 30}, " + " '$or' : [ { 'flag' : 'ALBANIA}, " + " { 'flag' : 'SAN MARINO'} ] }");

DBCursor cursor = db.find((DBObject) query);

com.mongo.util.JSON

sábado 18 de febrero de 12

Además...

Gestión de excepciones

Gestión recursos

DB, Collección, Cursores, DBObjects...

Transformaciones Objeto JSON

sábado 18 de febrero de 12

Spring Data MongoDB

sábado 18 de febrero de 12

Spring DataObjetivo:

Proporcionar un mecanismo homogéneo y completo para el acceso a BD NoSQL

Multiples proyectos:

Soportados:

MongoDB, Redis, Neo4j, Hadoop, GemFire, RiaK

En proceso:

CouchDB, Hbase, Cassandra

sábado 18 de febrero de 12

Spring Data y MongoDB

XML namespace para configurar driver Mongo

MongoTemplate

Conversión de excepciones automática

Conversión Configurable

JMX monitoring

sábado 18 de febrero de 12

Importando Spring Data

sábado 18 de febrero de 12

Importando Spring Data

<repository> <id>spring-release</id> <name>Spring Maven Release Repository</name> <url>http://repo.springsource.org/libs-release</url></repository>

<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.0.1.RELEASE</version></dependency>

sábado 18 de febrero de 12

Namespace

sábado 18 de febrero de 12

Namespace

<?xml  version="1.0"  encoding="UTF-­‐8"?><beans  xmlns="http://www.springframework.org/schema/beans"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-­‐instance"     xmlns:mongo="http://www.springframework.org/schema/data/mongo"   xmlns:context="http://www.springframework.org/schema/context"   xsi:schemaLocation="http://www.springframework.org/schema/beans  

   http://www.springframework.org/schema/beans/spring-­‐beans.xsd            http://www.springframework.org/schema/data/mongo            http://www.springframework.org/schema/data/mongo/spring-­‐mongo-­‐1.0.xsd

         http://www.springframework.org/schema/context            http://www.springframework.org/schema/context/spring-­‐context.xsd">

</beans>

sábado 18 de febrero de 12

Namespace

<?xml  version="1.0"  encoding="UTF-­‐8"?><beans  xmlns="http://www.springframework.org/schema/beans"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-­‐instance"     xmlns:mongo="http://www.springframework.org/schema/data/mongo"   xmlns:context="http://www.springframework.org/schema/context"   xsi:schemaLocation="http://www.springframework.org/schema/beans  

   http://www.springframework.org/schema/beans/spring-­‐beans.xsd            http://www.springframework.org/schema/data/mongo            http://www.springframework.org/schema/data/mongo/spring-­‐mongo-­‐1.0.xsd

         http://www.springframework.org/schema/context            http://www.springframework.org/schema/context/spring-­‐context.xsd">

</beans>

<mongo:db-­‐factory  dbname="vts"/>

sábado 18 de febrero de 12

Namespace

<?xml  version="1.0"  encoding="UTF-­‐8"?><beans  xmlns="http://www.springframework.org/schema/beans"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-­‐instance"     xmlns:mongo="http://www.springframework.org/schema/data/mongo"   xmlns:context="http://www.springframework.org/schema/context"   xsi:schemaLocation="http://www.springframework.org/schema/beans  

   http://www.springframework.org/schema/beans/spring-­‐beans.xsd            http://www.springframework.org/schema/data/mongo            http://www.springframework.org/schema/data/mongo/spring-­‐mongo-­‐1.0.xsd

         http://www.springframework.org/schema/context            http://www.springframework.org/schema/context/spring-­‐context.xsd">

</beans>

<mongo:db-­‐factory  dbname="vts"/>

  <bean  id="mongoTemplate"  class="org.springframework.data.mongodb.core.MongoTemplate">     <constructor-­‐arg  name="mongoDbFactory"  ref="mongoDbFactory"  />   </bean>

sábado 18 de febrero de 12

MongoTemplate

Identifica la colección

Convierte query a JSON

Convierte respuesta (“_class”)

Gestiona las conexiones y cursores

Convierte las excepciones

<bean  id="mongoTemplate"  class="org.springframework.data.mongodb.core.MongoTemplate">   <constructor-­‐arg  name="mongoDbFactory"  ref="mongoDbFactory"  /></bean>

sábado 18 de febrero de 12

MongoTemplate - Consultas

sábado 18 de febrero de 12

MongoTemplate - Consultas

public class MongoTemplate implements MongoOperations, ApplicationContextAware {

public <T> T findOne(Query query, Class<T> entityClass)

public <T> List<T> find(Query query, Class<T> entityClass)

public <T> T findById(Object id, Class<T> entityClass)

public <T> List<T> findAll(Class<T> entityClass)

}

sábado 18 de febrero de 12

MongoTemplate - Consultas

public class MongoTemplate implements MongoOperations, ApplicationContextAware {

public <T> T findOne(Query query, Class<T> entityClass)

public <T> List<T> find(Query query, Class<T> entityClass)

public <T> T findById(Object id, Class<T> entityClass)

public <T> List<T> findAll(Class<T> entityClass)

} public <T> T findOne(Query query, Class<T> entityClass, String collectionName)

....

sábado 18 de febrero de 12

Consultas

Consultas “SQL-like”

SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”; RDBMS:

sábado 18 de febrero de 12

Consultas

Consultas “SQL-like”

SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;

{ “flag” : “ALBANIA” }

Las consultas se hacen también en JSON

RDBMS:

Mongo:

sábado 18 de febrero de 12

Consultas

Consultas “SQL-like”

SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;

{ “flag” : “ALBANIA” }

Las consultas se hacen también en JSON

DBCollection vessels = db.getCollection("vessel");

DBObject query = new BasicDBObject();query.put("flag", "ALBANIA"); DBCursor albanianShips = vessels.find(query);while (albanianShips.hasNext()) { DBObject result = albanianShips.next(); // Create Vessel object from DBObject}

RDBMS:

Mongo:

Mongo

Driver:

sábado 18 de febrero de 12

Consultas

Consultas “SQL-like”

SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;

{ “flag” : “ALBANIA” }

Las consultas se hacen también en JSON

Query query = new Query(Criteria.where("flag").is("ALBANIA");

List<Vessel> vessels = mongoTemplate.find(query, Vessel.class);

Utilizado para

Identificación de la colección

Serialización JSON

RDBMS:

Mongo:

sábado 18 de febrero de 12

Serialización automática

sábado 18 de febrero de 12

Serialización automática

{  "_id"  :  "224000999",    "_class"  :  "com.vts.model.Vessel",    "flag"  :  "ALBANIA",    "name"  :  "Sample  NOT_AVAILABLE  Vessel  224000999",    "callsign"  :  "SV224000999",    "toBow"  :  25,    "toStern"  :  5,    "toPort"  :  5,    "toStarboard"  :  5,    "comments"  :  "Sample  vessel  created  automatically  for  test  purposes"  }

sábado 18 de febrero de 12

Consultas complejasConcatenación de consultas

sábado 18 de febrero de 12

Consultas complejasConcatenación de consultas

SELECT * FROM VESSELS WHERE length < 90 AND length > 30ORDER BY lastUpdate;

sábado 18 de febrero de 12

Consultas complejasConcatenación de consultas

SELECT * FROM VESSELS WHERE length < 90 AND length > 30ORDER BY lastUpdate;

{ “length” : { $lt : 90, $gt : 30}}

sábado 18 de febrero de 12

Consultas complejasConcatenación de consultas

SELECT * FROM VESSELS WHERE length < 90 AND length > 30ORDER BY lastUpdate;

{ “length” : { $lt : 90, $gt : 30}}

DBObject query = new BasicDBObject();DBObject condition = new BasicDBObject("$lt",90);condition.put("$gt",30);query.put("length", condition);

DBObject [] flags = {new BasicDBObject("flag", "ALBANIA"), new BasicDBObject("flag", "SAN MARINO")

};query.put("$or", flags);

vessels.find(query);

sábado 18 de febrero de 12

Consultas complejasConcatenación de consultas

SELECT * FROM VESSELS WHERE length < 90 AND length > 30ORDER BY lastUpdate;

{ “length” : { $lt : 90, $gt : 30}}

sábado 18 de febrero de 12

Consultas complejasConcatenación de consultas

SELECT * FROM VESSELS WHERE length < 90 AND length > 30ORDER BY lastUpdate;

{ “length” : { $lt : 90, $gt : 30}}

Criteria criteria = Criteria.where("length");criteria.gte(from);criteria.lte(to);

Query query = new Query(criteria);query.sort().on("lastUpdate", Order.ASCENDING);

List<Vessel> vessels = mongoTemplate.find(query, Vessel.class);

sábado 18 de febrero de 12

MongoTemplate - inserciones

sábado 18 de febrero de 12

MongoTemplate - inserciones

public class MongoTemplate implements MongoOperations, ApplicationContextAware {

public void save(Object objectToSave)

public void save(Object objectToSave, String collectionName)

}

sábado 18 de febrero de 12

AbstractRepository

sábado 18 de febrero de 12

AbstractRepository

public abstract class AbstractMongoRepository<T> {

@Inject protected MongoTemplate mongoTemplate; /** Clase que utiliza Mongo para identificar el nombre de la coleccion */ private Class<T> persistentClass;

protected AbstractService(Class<T> persistentClass) { this.persistentClass = persistentClass; }

public String determineCollection() { return persistentClass.getSimpleName(); }}

sábado 18 de febrero de 12

AbstractRepository

sábado 18 de febrero de 12

AbstractRepositorypublic abstract class AbstractMongoRepository<T> {

public void save(T e) { mongoTemplate.save(e, determineCollection()); } public void save(Collection<T> entities) { for (T e : entities) { save(e); } } public void removeById(String id) { Object e = findById(id); if (e != null) { mongoTemplate.remove(e, determineCollection()); } } public T findById(String id) { T t = mongoTemplate.findById(id, persistentClass); if (t == null) { throw new ObjectNotFoundException(persistentClass, id); } return t; }}

sábado 18 de febrero de 12

VesselRepository

sábado 18 de febrero de 12

VesselRepository

public class VesselRepository extends AbstractMongoRepository<Vessel> {

public VesselRepository() { super(Vessel.class); }

}

sábado 18 de febrero de 12

A tener en cuenta

sábado 18 de febrero de 12

El caso de BitSet

Cuidado con los campos transient

sábado 18 de febrero de 12

El caso de BitSet

public class BitSet implements Cloneable, java.io.Serializable {

/** The internal field corresponding to the serialField "bits". */ */ private long[] words;

/** The number of words in the logical size of this Bitset */ private transient int wordsInUse = 0;

private void expandTo(int wordIndex) { int wordsRequired = wordIndex+1; if (wordsInUse < wordsRequired) { ensureCapacity(wordsRequired); wordsInUse = wordsRequired; } }}

Cuidado con los campos transient

sábado 18 de febrero de 12

Conversión Manual

sábado 18 de febrero de 12

Conversión Manual

public  class  BitSetReadConverter  implements  Converter<DBObject,  BitSet>  {

  @Override   public  BitSet  convert(DBObject  source)  {     BasicDBList  words  =  (BasicDBList)source.get("words");     BitSet  bitset  =  new  BitSet();     int  index  =  0;     for  (Object  word  :  words)  {       long  value  =  (Long)word;       while  (value  !=  0L)  {

      if  ((value  &  1L)  !=  0)  {                bitset.set(index);         }         ++index;         value  =  value  >>>  1;       }         }         return  bitset;   }}

sábado 18 de febrero de 12

Conversión ManualPorque a veces lo automático no funciona

sábado 18 de febrero de 12

Conversión ManualPorque a veces lo automático no funciona

<?xml version="1.0" encoding="UTF-8"?><beans>

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> <constructor-arg name="mongoConverter" ref="mappingConverter" /> </bean> <mongo:db-factory dbname="vts"/> <mongo:mapping-converter> <mongo:custom-converters> <mongo:converter> <bean class="com.vts.db.BitSetReadConverter"/> </mongo:converter> </mongo:custom-converters> </mongo:mapping-converter>

</beans>

sábado 18 de febrero de 12

Queries con multiples valores

sábado 18 de febrero de 12

Queries con multiples valores

Query query = new Query( Criteria .where("length").gte(20) .and("length").lt(60));

sábado 18 de febrero de 12

Queries con multiples valores

Query query = new Query( Criteria .where("length").gte(20) .and("length").lt(60));

DEBUG MongoTemplate - find using query: { "length" : { "$lt" : 60} }

sábado 18 de febrero de 12

Queries con multiples valores

sábado 18 de febrero de 12

Queries con multiples valores

Query query = new Query( Criteria .where("length").gte(20).lte(60));

sábado 18 de febrero de 12

Queries con multiples valores

Query query = new Query( Criteria .where("length").gte(20).lte(60));

DEBUG MongoTemplate - find using query: { "toBow" : { "$gte" : 20 , "$lte" : 60} }

sábado 18 de febrero de 12

Conclusiones

Reducción del número de tablas (87x2 vs 5)

Optimización en el rendimiento de escrituras

Simplificación de los DAOs con Spring-Data

Otras ventajas:

Documentos en formato de Respuesta REST

interfaz Javascript en la consola

sábado 18 de febrero de 12

Q&A

David Gómez@dgomezg

sábado 18 de febrero de 12