martes, 4 de agosto de 2015

Spring 4.2 + Jpa 2.1 + Hibernate 4.3


Ahora vamos a montar un proyecto de spring, configurando Jpa 2.1 implementado por hibernate 4.3.
Como B.D vamos a usar una embebida (HSQLBD), para que el proyecto sea totalmente autónomo.
Para lo cual vamos a seguir los siguientes pasos:
  • Establecer las dependencias necesarias para un proyecto Spring.
  • Montar la configuración de spring.
  • Montar la configuración de spring JPA.
  • Crear el entorno de test.
  • Montar un test, para que podamos probar nuestra configuración.
El ejemplo de este articulo lo podéis descargar del siguiente enlace https://github.com/blancoparis-tfc/SpringHibernate

Dependencias:

Primero vamos a ver que librerías que vamos a necesitar:

Spring

Las dependencias relacionadas con la versión de spring, en nuestro ejemplo vamos a utilizar la versión 4.2.0.RELEASE.
  • Spring-context: Es la parte de spring encargada de levantar un contenedor de beans.
  • Spring-orm: Es el modulo de spring que utilizaremos para trabajar con los orm, que en nuestro caso sera hibernate como implementación de JPA 2.1.
  compile 'org.springframework:spring-context:4.2.0.RELEASE'
  compile 'org.springframework:spring-orm:4.2.0.RELEASE'

JPA2.1 + Hibernate 4.3


Las dependencias, relacionada con jpa2.1 + hibernate 4.3.10.FINAL.


  • Hibernate-core: Es la implementación de hibernate normal.
  • Hibernate-entitymanager: Es la integración de hibernate con JPA.
    compile 'org.hibernate:hibernate-core:4.3.10.Final'
    compile 'org.hibernate:hibernate-entitymanager:4.3.10.Final'

B.D


Las dependencias, relacionadas como la B.D, que en nuestro caso sera la libreria de HSQLBD mas una implementación de el datasource.


  • Hsqlbd: Es la bd embebida que vamos a utilizar.
  • commons-dbcp: Es una implementación para el datasource, en un proyecto de producición podemos utilizar mejor este c3p0.
    compile 'commons-dbcp:commons-dbcp:1.4'
    compile 'org.hsqldb:hsqldb:2.3.3'

Entorno de test:


La librería que vamos a utilizar, para realizar los test, que en nuestro caso será junit + la librería de test de spring.


  • Junit: Es la librería que vamos a utilizar para realizar los test unitarios.
  • Spring-test: Es la librería para poder lanzar spring, desde los entornos de test.
    testCompile group: 'junit', name: 'junit', version: '4.+'
    testCompile 'org.springframework:spring-test:4.2.0.RELEASE'



Crear el proyecto


Ahora que ya sabemos cuales son las dependencias que necesitamos, vamos a crear el fichero de gradle para poder montar nuestro proyecto.


  • Le tenemos que indicar, que es un proyecto de java y se va integrar con eclipse, para lo cual usaremos los pluging de (java,eclipse)
  • La indicamos con que maquina de java, vamos a trabajar utilizando la variable sourceCompatibility
  • Le indicamos que vamos a usar los repositorios de maven:
  • Ponemos las dependencias que necesitemos.
apply plugin: 'java'
apply plugin: 'eclipse'

sourceCompatibility = 1.8
version = '1.0'

repositories {
    mavenCentral()
}

dependencies {
  compile 'org.springframework:spring-context:4.2.0.RELEASE'
  compile 'org.springframework:spring-orm:4.2.0.RELEASE'
    compile 'commons-dbcp:commons-dbcp:1.4'
    compile 'org.hsqldb:hsqldb:2.3.3'
    compile 'org.hibernate:hibernate-core:4.3.10.Final'
    compile 'org.hibernate:hibernate-entitymanager:4.3.10.Final'
    
    testCompile group: 'junit', name: 'junit', version: '4.+'
    testCompile 'org.springframework:spring-test:4.2.0.RELEASE'
    
}

Configuración de Spring:


Aquí vamos a ver las configuraciones necesarias para spring, en mi caso las colocaremos en el paquete org.dbp.core.config.

Configuración básica de spring


Vamos a ver que necesitamos para poder configurar Spring, mínimo. En este caso la verdad, lo único que le tenemos que indicar a spring en que paquete van a estar los beans con los que vamos a trabajar en nuestro caso sera (org.dbp.service).


  • @Configuration: Le indicamos a spring, que es una clase para configurar spring.
  • @ComponentScan: Le indicamos los paquetes donde se encontraran los beans del contexto, que en nuestro caso “org.dbp.service”
package org.dbp.core.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@ComponentScan(basePackages = "org.dbp.service")
public class TestConfiguracion {

}

Configuración de JPA + Hibernate:


Para la configuración de la JPA, vamos a crear otra clase independiente donde estableceremos toda la configuración necesaria para la persistencia y que inyectaremos en la configuración general.

Para la persistencia tendremos que configurar los siguientes aspectos:


  • Habilitar las transaciones: @EnableTransactionManagement
  • El datasource: Configuraremos el datasource, que realizara la conexión con la B.D, con la que vamos a trabajar. (Si el día de mañana quisiéramos poner un pool de conexión aquí es donde se establecerá).
  • El entityManagerFactory: Configuramos la factoria de los entityManager de JPA, que es donde pondremos la configuración de JPA necesarias.
  • Las transaciones: Aquí configuramos las transacciones de jpa, con spring (Tengamos en cuenta que estas transacciones serán por orientación aspectos).
package org.dbp.core.config;

import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class TestJpaConfiguration {

 @Bean
 public DataSource getDataSource() {
     BasicDataSource dataSource = new BasicDataSource();
  dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
  dataSource.setUrl("jdbc:hsqldb:mem:pruebas");
  dataSource.setUsername("sa");
  dataSource.setPassword("");
     return dataSource;
 }
 
 /**
  * Configuramos el entity manager en JPA. - Le indicamos el data source con
  * el que va a trabajar. - Le indicamos el paquete donde se encuentran las
  * clases. - Le pasamos el adaptador de JPA que en nuestro caso sera
  * hibernate. - Por otro lado le pasamos las propiedades.
  * 
  * @return
  */
 @Bean
 public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
  LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
  em.setDataSource(getDataSource());
  em.setPackagesToScan(new String[] { "org.dbp.bom" });
  JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
  em.setJpaVendorAdapter(vendorAdapter);
  em.setJpaProperties(propiedadesAdicionalesJpa());
  return em;
 }
 
 /**
  * Le indicamos el tipo de configuraci�n que nos interesa para hibernate -
  * Le indicmaos que cada vez que entremos borre y cree las B.D. - Le
  * indicamos que utilice el dialecto con HSQL.
  * 
  * Nota: este m�todo no es parte de la configuraci�n de spring.
  * 
  * @return
  */
 private Properties propiedadesAdicionalesJpa() {
  return new Properties() {
   {
    setProperty("hibernate.hbm2ddl.auto", "create");
    setProperty("hibernate.jdbc.batch_size", "20");
    setProperty("hibernate.show_sql", "true");
    setProperty("hibernate.dialect","org.hibernate.dialect.HSQLDialect");
    setProperty("hibernate.hbm2ddl.import_files","/META-INF/inicializar.sql");
   }
  };
 }

 /**
  * Configura las transaciones en JPA.
  * 
  * @return
  */
 @Bean
 public PlatformTransactionManager transactionManager(EntityManagerFactory emf){ 
  JpaTransactionManager transactionManager = new JpaTransactionManager();
  transactionManager.setEntityManagerFactory(emf);
  return transactionManager;
 }
 
}

Ahora simplemente tenemos que indicarle en la configuración general que importe esta configuración con @Import({TestJpaConfiguration.class})




Creamos una entidad.


Para poder probar la configuración, vamos a crear una entidad, en nuestro caso sera el típico ejemplo de usuario con los campos (id,login y descripción).

package org.dbp.bom;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Usuario implements Serializable{

 @Id
 private Long id;
 
 private String login;
  
 private String nombre;

 public String getLogin() {
  return login;
 }

 public void setLogin(String login) {
  this.login = login;
 }

 public String getNombre() {
  return nombre;
 }

 public void setNombre(String nombre) {
  this.nombre = nombre;
 }

 public Long getId() {
  return id;
 }

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

}

Test, para probar la configuración


Para poder probar esta configuración básica, la vamos a poner en el entorno de test,  y llamando a un test, consultamos un registro y insertamos otro y así podemos ver que funciona correctamente.
package org.dbp.core.config;

import static org.junit.Assert.*;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.dbp.bom.Usuario;
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;
/**
 * Test para validar la configuración del JPA.
 * @author david
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@ContextConfiguration(classes = TestConfiguracion.class)
public class ConfigurationJpaTest {

 @PersistenceContext EntityManager em;
 
 @Test
 public void testRecuperarUnUsuario(){
  Usuario usuario=em.find(Usuario.class, 1L);
  assertEquals("El id del usuario 1",new Long(1L),usuario.getId());
  assertEquals("El login del usaurio","dblanco",usuario.getLogin());
  assertEquals("El nombre","david blanco paris",usuario.getNombre());
 }
 
 @Test
 public void testInsertarUsuario(){
  Usuario usuario=new Usuario();
  usuario.setId(2L);
  usuario.setLogin("perico");
  usuario.setNombre("Perico el de los palotes");
  em.persist(usuario);
 }
 
}

Conclusión


En este articulo hemos visto como configurar, un proyecto de spring + jpa. Para no complicar en exceso la configuración lo he montado en un entorno de test, pero ese mismo fichero se lleva a una configuración de spring y nos vale igual.

2 comentarios: