viernes, 2 de marzo de 2012

Spring data + mongoDB

Bueno vamos a hacer otro ejemplo con Spring data y mongoDB. La idea seria que tengo un usuario y debo guardarlo en una base NoSQL como MongoDB.

Antes de empezar es necesario instalar mongoDB y levantar la base como lo indica el siguiente tutorial:

http://emanuelpeg.blogspot.com/2012/02/instalar-mongodb-en-linux.html

Vamos hacer el proyecto con maven:

mvn archetype:generate

Creamos el proyecto comunacho de maven, con los nombres de paquetes que deseen. Vamos a agregar al pom las dependencias necesarias:

		
			org.springframework.data
			spring-data-mongodb
			1.0.1.RELEASE
		
		
		
			org.springframework
			spring-core
			${spring.version}
		

		
			org.springframework
			spring-context
			${spring.version}
		

		
			org.springframework
			spring-aop
			${spring.version}
		

		
			org.springframework
			spring-aspects
			${spring.version}
		

		
			org.springframework
			spring-tx
			${spring.version}
		

		
			junit
			junit
			4.10
			test
		

		
			org.springframework
			spring-test
			${spring.version}
			test
		


donde:


	3.1.0.RELEASE



Además agregamos el repositorio:

	
		
			spring-release
			Spring Maven Release Repository
			http://repo.springsource.org/libs-release
		
	


Hacemos maven para agregar las dependencias:

mvn clean install
mvn eclipse:eclipse

Ahora importamos el proyecto a eclipse o su IDE favorita, la mía es eclipse.

Creamos la clase User, vamos a hacer antes una clase padre que contenga las particularidades generales de las clases del modelo que van a hacer persistidas:

public abstract class PersistentEntity {
	@Id
	private Long id;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}


}


Ahora hacemos la clase User:

@Document
public class User extends PersistentEntity {

	private String userName;
	
	private String password;
	
	private List emails = new ArrayList();
	
	public User() {
	}
	
	public User(String userName, String password) {
		super();
		this.userName = userName;
		this.password = password;
	}

	public User(String userName, String password, List emails) {
		this(userName, password);
		this.emails = emails;
	}

	//getters and setters

} 


Vamos a escribir un DAO para ello vamos hacer lo siguiente vamos a generar una clase genérica que contenga métodos genéricos de acceso a datos y vamos a heredar de esta clase; a la vez cada clase va a tener su interfaz que la describa.

La interfaz del genericDAO:

package org.assembly.edda.repository;

import java.io.Serializable;
import java.util.List;

import org.assembly.edda.model.PersistentEntity;

public interface GenericDAO {
	
	T get(ID id);
	
	T save(T object);
	
	void delete(T object);
	
	List findAll();
} 


Su implementación:

package org.assembly.edda.dao;

import java.io.Serializable;
import java.util.List;

import org.assembly.edda.model.PersistentEntity;
import org.assembly.edda.model.User.User;
import org.assembly.edda.repository.GenericDAO;
import org.springframework.data.mongodb.core.MongoTemplate;

/**
 * @author emanuel
 *
 */
public abstract class GenericDAOImpl implements GenericDAO {

	private MongoTemplate mongoTemplate;
	
	public void setMongoTemplate(MongoTemplate mongoTemplate) {
		this.mongoTemplate = mongoTemplate;
	}
	
	protected abstract Class getEntityClass();
	
	public T get(ID id) {
		return (T) mongoTemplate.findById(id, getEntityClass());
	}

	public T save(T objectToSave) {
		mongoTemplate.save(objectToSave);
		return objectToSave;
	}

	public void delete(T objectToDelete) {
		mongoTemplate.remove(objectToDelete);
	}
	
	public List findAll() {
		return mongoTemplate.findAll(getEntityClass());
	}

}


Ahora la interfaz de UserDAO:

package org.assembly.edda.repository.user;

import org.assembly.edda.model.User.User;
import org.assembly.edda.repository.GenericDAO;

public interface UserDAO extends GenericDAO{

}


y su implementación:

package org.assembly.edda.dao.user;

import org.assembly.edda.dao.GenericDAOImpl;
import org.assembly.edda.model.User.User;
import org.assembly.edda.repository.user.UserDAO;

/**
 * @author emanuel
 *
 */
public class UserDAOImpl extends GenericDAOImpl implements UserDAO{

	
	@Override
	protected Class getEntityClass() {
		return User.class;
	}

}


Ahora vamos a escribir el ApplicationContext.xml de spring:



        
    
    
    
    	
    
    
    
    	
    	
    

	
    
    	
    
    
	
	
	
	
		
		
	
    



Bueno con esto estamos, solo debemos testar para ver si funciona. Creamos un test; ojo tener levantada la base cuando se lo corre. Para testear esto lo voy hacer más difícil voy a generar una clase padre generica y luego el test concreto (solo para ver como queda)

package org.assembly.edda.dao;

import static org.junit.Assert.*;
import java.util.List;

import org.assembly.edda.model.PersistentEntity;
import org.assembly.edda.repository.GenericDAO;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;


/**
 * @author emanuel
 *
 */
@ContextConfiguration(locations = "classpath:applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
public abstract class GenericDAOTest> {
	
	protected abstract DAO getDAO();
	protected abstract T createObject();
	protected abstract T createOtherObject();
	protected abstract void assertEqualsObject(T object, T objectSaved);
	
	@Test
	public void find() {
		T object = createObject();
		getDAO().save(object);
		
		T objectSaved = getDAO().get(object.getId());
		assertEqualsObject(object, objectSaved);
	}

	
	@Test
	public void findAll() {
		T object = createObject();
		getDAO().save(object);
		
		T otherObject = createOtherObject();
		getDAO().save(otherObject);
		
		List all = getDAO().findAll();
		
		assertEquals(2, all.size());
	}

}

Y la implementación del test:

package org.assembly.edda.dao.user;

import static org.junit.Assert.*;

import javax.annotation.Resource;

import org.assembly.edda.dao.GenericDAOTest;
import org.assembly.edda.model.User.User;



public class UserDAOTest extends GenericDAOTest {

	@Resource
	private UserDAOImpl dao;
	
	public void setDao(UserDAOImpl dao) {
		this.dao = dao;
	}
	
	@Override
	protected UserDAOImpl getDAO() {
		return dao;
	}

	@Override
	protected User createObject() {
		User user = new User("Pepe", "0303456yalalala");
		user.setId(4l);
		return user;
	}

	@Override
	protected User createOtherObject() {
		User user = new User("Pepe", "0303456yalalala");
		user.setId(5l);
		return user;
	}
	
	@Override
	protected void assertEqualsObject(User object, User objectSaved) {
		assertEquals(object.getId(), objectSaved.getId());
		assertEquals(object.getUserName(), objectSaved.getUserName());
		assertEquals(object.getEmails(), objectSaved.getEmails());
		assertEquals(object.getPassword(), objectSaved.getPassword());
	}


}



Eso es todo amigos!!