Librería de acceso a datos con Spring y JPA
0. Índice de contenidos.
- 1. Entorno
- 2. Introducción
- 3. Creando el proyecto con Maven
- 4. Configurando las dependencias del proyecto
- 5. Configurando Spring
- 6. Configurando JPA
- 7. Creando un DAO genérico
- 8. Creando la entidad Persona
- 9. Creando la clase de persistencia para la entidad Persona
- 10. Vamos a probarlo
- 11. Conclusiones
1. Entorno
Este tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil Mac Book Pro 17″ (2,6 Ghz Intel Core
i7, 8 GB
DDR3) - Sistema Operativo: Mac OS X Snow Leopard 10.6.4
- Spring 3.0.4
- Maven 2.2.1
- Eclipse 3.6 (Helios) con M2Eclipse y Spring IDE
2. Introducción
Este tutorial lo voy a aprovechar para crear una librería de acceso al esquema de datos que voy a utilizar en el resto de tutoriales que necesiten un acceso a base de datos.
Uno de los problemas más comunes que nos encontramos cuando participamos en proyectos ya comenzados es que todo el código de acceso a datos se repite en todos y cada uno de los proyectos.
En estos casos lo mejor que se puede hacer es crear una librería para cada uno de los esquemas de base de datos que intervengan en el proyecto. Como vamos a ver en este tutorial.
3. Creando el proyecto con Maven
En este tipo de proyectos en los que vamos a utilizar librerías
de
terceros como Spring, se hace especialmente útil la
utililización de
una herramienta de gestión de dependencias como Maven. Teniendo
Maven
ya instalado en nuestra máquina lo único que tenemos que
hacer es abrir
un terminal y situarnos en el directorio donde vayamos a crear el
proyecto:
1 |
mvn archetype:create -DgroupId=com.autentia -DartifactId=model-tutoriales |
4. Configurando las dependencias del proyecto
Con el fin de que la edición del proyecto sea más
cómoda podemos
importarlo a un IDE como Eclipse. Para hacer esto, contamos con el
plugin M2Eclipse que es la evolución del conocido EclipseIAM.
Para configurar las dependencias editamos el fichero pom.xml del
proyecto, añadiendo las siguientes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelversion>4.0.0</modelversion> <groupid>com.autentia</groupid> <artifactid>model-tutoriales</artifactid> <version>1.0-SNAPSHOT</version> <name>model-tutoriales</name> <description>Librería de acceso a datos para la base de datos "tutoriales"</description> <build> <plugins> <plugin> <artifactid>maven-compiler-plugin</artifactid> <configuration> <encoding>UTF-8</encoding> <source>1.6 <target>1.6</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupid>commons-lang</groupid> <artifactid>commons-lang</artifactid> <version>2.5</version> </dependency> <dependency> <groupid>javax.persistence</groupid> <artifactid>persistence-api</artifactid> <version>1.0</version> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-core</artifactid> <version>3.0.4.RELEASE</version> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-tx</artifactid> <version>3.0.4.RELEASE</version> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-orm</artifactid> <version>3.0.4.RELEASE</version> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-hibernate3</artifactid> <version>2.0.8</version> </dependency> <dependency> <groupid>org.hibernate</groupid> <artifactid>hibernate-entitymanager</artifactid> <version>3.3.1.ga</version> </dependency> <dependency> <groupid>postgresql</groupid> <artifactid>postgresql</artifactid> <version>9.0-801.jdbc4</version> </dependency> <dependency> <groupid>concurrent</groupid> <artifactid>concurrent</artifactid> <version>1.3.3</version> </dependency> <dependency> <groupid>javax.annotation</groupid> <artifactid>jsr250-api</artifactid> <version>1.0</version> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-test</artifactid> <version>3.0.4.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupid>junit</groupid> <artifactid>junit</artifactid> <version>4.8.2</version> <scope>test</scope> </dependency> <dependency> <groupid>org.hsqldb</groupid> <artifactid>hsqldb</artifactid> <version>1.8.0.10</version> <scope>test</scope> </dependency> </dependencies> </project> |
Estamos definiendo que el proyecto lo vamos a implementar con Spring y la especificación JPA 1.0 con Hibernate. Además en desarrollo vamos a utilizar PostgreSQL, pero para los tests vamos a utilizar una base de datos en memoria como HSQLDB.
5. Configurando Spring
Para configurar Spring vamos a crear el fichero application-context-model-tutoriales.xml dentro de la carpeta src/main/resources de nuestro proyecto, con el siguiente contenido:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd" default-autowire="byName"> <context:annotation-config /> <context:component-scan base-package="com.autentia.tutoriales" /> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceXmlLocation" value="classpath:/META-INF/persistence.xml" /> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> </beans> |
En este fichero estamos definiendo que vamos a utilizar anotaciones y especificamos que archivo se va a encargar de definir el acceso a la base de datos a través de JPA.
6. Configurando JPA
Como hemos definido anteriormente tenemos que crear un fichero llamado persistence.xml dentro de la carpeta src/main/resources/META-INF con el siguiente contenido:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="tutoriales" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.connection.url" value="jdbc:postgresql:tutoriales"/> <property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/> <property name="hibernate.connection.password" value="autentia"/> <property name="hibernate.connection.username" value="postgres"/> <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/> <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> <property name="hibernate.connection.pool_size" value="8"/> <property name="transaction.factory_class" value="org.hibernate.transaction.JDBCTransactionFactory"/> <property name="hibernate.format_sql" value="true"/> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence> |
7. Creando un DAO genérico
Con el fin de no repetir los mismos métodos en todas las clases del proyecto, vamos a crear un DAO genérico con los métodos comunes de acceso a datos, que vamos a definir en la siguiente interfaz:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.autentia.tutoriales.dao; import java.io.Serializable; import java.util.List; public interface GenericDAO <T, PK extends Serializable> { List<T> getAll(Class<T> typeClass); T findByPK(Class<T> typeClass, PK id); void update(T object); void remove(T object); void insert(T object); List<T> getPaginated(Class<T> typeClass, int startPosition, int maxResult); List<T> getOrderedPaginated(Class<T> typeClass, int startPosition, int maxResult, String order, int dir); } |
En este caso vamos a implementar esta interfaz utilizando Spring y JPA con el siguiente código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
package com.autentia.tutoriales.dao.imp.jpa; import java.io.Serializable; import java.util.List; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.springframework.orm.jpa.support.JpaDaoSupport; import org.springframework.transaction.annotation.Transactional; import com.autentia.tutoriales.dao.GenericDAO; @PersistenceContext(unitName = "tutoriales") public class GenericDAOJPAImpl<T, PK extends Serializable> extends JpaDaoSupport implements GenericDAO<T, PK> { @Transactional public void insert(T t) { getJpaTemplate().persist(t); } @Transactional(readOnly = true) public T findByPK(Class<T> typeClass, PK id) { return getJpaTemplate().find(typeClass, id); } @Transactional(readOnly = true) @SuppressWarnings("unchecked") public List<T> getAll(Class<T> typeClass) { final StringBuilder sql = new StringBuilder("select c from ").append( typeClass.getSimpleName()).append(" c"); return (List<T>) getJpaTemplate().find(sql.toString()); } @Transactional public void remove(T object) { getJpaTemplate().remove(getJpaTemplate().merge(object)); } @Transactional public void update(T object) { getJpaTemplate().merge(object); } @SuppressWarnings("unchecked") @Transactional(readOnly = true) public List<T> getPaginated(Class<T> typeClass, int startPosition, int maxResult) { final StringBuilder sql = new StringBuilder("select c from ").append( typeClass.getSimpleName()).append(" c"); final Query query = getJpaTemplate().getEntityManagerFactory() .createEntityManager().createQuery(sql.toString()); query.setFirstResult(startPosition); query.setMaxResults(maxResult); return (List<T>) query.getResultList(); } @SuppressWarnings("unchecked") @Transactional(readOnly = true) public List<T> getOrderedPaginated(Class<T> typeClass, int startPosition, int maxResult, String order, int dir) { String direccion = "ASC"; if (dir == 2) { direccion = "DESC"; } final StringBuilder sql = new StringBuilder("select c from ") .append(typeClass.getSimpleName()).append(" c order by ") .append(order).append(" ").append(direccion); final Query query = getJpaTemplate().getEntityManager().createQuery( sql.toString()); query.setFirstResult(startPosition); query.setMaxResults(maxResult); return (List<T>) query.getResultList(); } } |
Para esta implementación utilizamos la facilidades de Spring para JPA extendiendo de JPADaoSupport y con la anotación @PersistenceContext.
8. Creando la entidad Persona
Lo principal cuando utilizamos JPA es la definición de las entidades, en este caso lo vamos a hacer con anotaciones de esta forma:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
package com.autentia.tutoriales.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; @Entity public class Persona { private static final long serialVersionUID = -5763643296733667671L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "ID_PERSONA", unique = true, nullable = false, precision = 10) private Long idPersona; @Column(length = 256, name = "NOMBRE") private String nombre; @Column(length = 256, name = "APELLIDOS") private String apellidos; @Column(length = 256, name = "DIRECCION") private String direccion; public void setIdPersona(Long idPersona) { this.idPersona = idPersona; } public Long getIdPersona() { return idPersona; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public String getApellidos() { return apellidos; } public void setApellidos(String apellidos) { this.apellidos = apellidos; } public String getDireccion() { return direccion; } public void setDireccion(String direccion) { this.direccion = direccion; } public int hashCode() { final HashCodeBuilder hcb = new HashCodeBuilder(); hcb.append(nombre); hcb.append(apellidos); hcb.append(direccion); return hcb.toHashCode(); } public boolean equals(Object obj) { if (obj == null){ return false; } if (obj == this){ return true; } if (this.getClass() != obj.getClass() ){ return false; } final EqualsBuilder eqb = new EqualsBuilder(); eqb.append(this.nombre, this.getClass().cast(obj).nombre); eqb.append(this.apellidos, this.getClass().cast(obj).apellidos); eqb.append(this.direccion, this.getClass().cast(obj).direccion); return eqb.isEquals(); } } |
De esta implementación cabe destacar la forma como hemos definido el id de la entidad para que sea un autonumérico. Además hay que fijarse como hemos definido los métodos hashCode() y equals(), que nos evitarán problemas a la hora de trabajar con la persistencia.
9. Creando la clase de persistencia para la entidad Persona
Como ya hemos implementado el DAO genérico, para crear la clase que se va a encargar de la persistencia de la entidad Persona, va a ser tan sencillo como definir la siguiente interfaz:
1 2 3 4 5 6 7 |
package com.autentia.tutoriales.dao; import com.autentia.tutoriales.model.Persona; public interface PersonaDAO extends GenericDAO<Persona, Long>{ } |
Y la implementación de la clase es tan sencillo como lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 |
package com.autentia.tutoriales.dao.imp.jpa; import org.springframework.stereotype.Repository; import com.autentia.tutoriales.dao.PersonaDAO; import com.autentia.tutoriales.model.Persona; @Repository("personaDAO") public class PersonaDAOJPAImpl extends GenericDAOJPAImpl<Persona, Long> implements PersonaDAO{ } |
Cabe destacar la utilización de la anotación @Repository que nos ahorra tener que definir un bean explícito en el fichero application-context-model-tutoriales.xml.
Con esto la entidad Persona ya tiene disponibles los métodos del DAO genérico, en caso de necesitar otros métodos específicos, habría que implementarlos en la clase PersonaDAOJPAImpl y definirlos en la interfaz PersonaDAO.
10. Vamos a probarlo
A fin de probar esta implementación vamos a definir un archivo application-context.xml y pesistence.xml específicos para las pruebas, donde vamos a utilizar una base de datos en memoria.
Para ello vamos a crear el fichero application-context-model-tutoriales-test.xml dentro de la carpeta src/test/resources con el siguiente contenido:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd" default-autowire="byName"> <context:annotation-config /> <context:component-scan base-package="com.autentia.tutoriales" /> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceXmlLocation" value="classpath:/META-INF/persistence-test.xml" /> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> </beans> |
La única diferencia con el anterior es la definición del fichero persistence-test.xml, que se almacena en la carpeta src/test/resources/META-INF con el siguiente contenido:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="tutoriales" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>com.autentia.tutoriales.model.Persona</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" /> <property name="hibernate.hbm2ddl.auto" value="create" /> <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" /> <property name="hibernate.connection.username" value="sa" /> <property name="hibernate.connection.password" value="" /> <property name="hibernate.connection.url" value="jdbc:hsqldb:mem:tutoriales" /> <property name="hibernate.showSql" value="true" /> <property name="hibernate.format_sql" value="true"/> <property name="transaction.factory_class" value="org.hibernate.transaction.JDBCTransactionFactory"/> <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/> <property name="hibernate.connection.pool_size" value="8"/> </properties> </persistence-unit> </persistence> |
Una vez configurado el entorno de pruebas sólo tenemos que implementar la siguiente clase con JUnit, donde vamos a probar la inserción, recuperación, modificación y eliminación de un registro de la entidad Persona.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
package com.autentia.tutoriales.dao.imp.jpa; import javax.annotation.Resource; import static org.junit.Assert.*; 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.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; import com.autentia.tutoriales.dao.PersonaDAO; import com.autentia.tutoriales.model.Persona; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:/application-context-model-tutoriales-test.xml" }) @Transactional @TransactionConfiguration(defaultRollback=true) public class PersonaDAOJPAImplTest { @Resource PersonaDAO personaDAO; @Test public void crudPersona(){ Persona persona = new Persona(); persona.setNombre("Nombre"); persona.setApellidos("Apellidos"); persona.setDireccion("Direccion"); personaDAO.insert(persona); assertEquals(new Long(1), persona.getIdPersona()); Persona personaRecuperada = personaDAO.findByPK(Persona.class, persona.getIdPersona()); personaRecuperada.setApellidos("Apellidos modificado"); personaDAO.update(personaRecuperada); personaRecuperada = personaDAO.findByPK(Persona.class, personaRecuperada.getIdPersona()); assertEquals("Apellidos modificado", personaRecuperada.getApellidos()); personaDAO.remove(personaRecuperada); } } |
La anotación @RunWith y @ContextConfiguration nos permiten levantar el contexto de Spring para que se produzca la inyección de la dependencia PersonaDAO.
11. Conclusiones
Hemos visto como crear una librería para acceder a un esquema de base de datos que podremos importar en cualquier proyecto que necesite trabajar con este esquema. De hecho yo voy a utilizarla en posteriores desarrollos de futuros tutoriales.
Saludos.
Hola Ruben, antes que nada quería agradecerte por el excelente tutorial, es muy claro y por sobre todo muy útil. Tengo un problema al querer realizar las pruebas, me sale un error en la carga del contexto de aplicación, revisé todo y se supone que esta todo bien. Podrías subir el código o decirme como puedo enviarte el mío para que me des una mano. Gracias. Saludos
Hola Ruben igualmente muchas gracias por el tutorial, pero tengo el mismo error que Booger. Como podemos solucionar esto? Muchas Gracias!
Ya corregi el error que tenia: la falla estaba en el Persistence.xml y el persistence-test.xml, no habia definido el nombre de mi base de datos en: tenia tutoriales. Espero que esto te sirva Booger
Hola gracias por todo Ruben, pero me sale un error en la carga del contexto de aplicación. He leido intentado hacer otros tutoriales de esta sitio y siempre o los dejan a medias o con errores. Un consejo si van a dar tutoriales es porque lo van a leer personas que estan aprendiendo. Se hacen preguntas y nunca se responden. Que estes bien y gracias por el tuto.
Hola gabohacker,
¿Podrías darme más información sobre cuál es el error que está dando? Por ejemplo, el log de la aplicación con la traza de la pila estaría genial.
Saludos.
4/04/2011 04:59:38 PM org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
INFO: @TestExecutionListeners is not present for class [class com.urbanalab.modelo.pruebas.PersonaDAOJPAImplTest]: using defaults.
4/04/2011 04:59:38 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [com/urbanalab/modelo/pruebas/applicationContext.xml]
4/04/2011 04:59:38 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@4720d62b: startup date [Mon Apr 04 16:59:38 COT 2011]; root of context hierarchy
4/04/2011 04:59:38 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@687bc899: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,personaDAO,org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor#0,entityManagerFactory,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor]; root of factory hierarchy
4/04/2011 04:59:38 PM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@687bc899: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,personaDAO,org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor#0,entityManagerFactory,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor]; root of factory hierarchy
4/04/2011 04:59:38 PM org.springframework.test.context.TestContextManager prepareTestInstance
GRAVE: Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@11e9c82e] to prepare test instance [com.urbanalab.modelo.pruebas.PersonaDAOJPAImplTest@b554d32]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:308)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:220)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:301)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:303)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name \\\’personaDAO\\\’ defined in file [C:\\\\Users\\\\Comba_Desarrollo1\\\\EclipseProjects\\\\Database\\\\target\\\\classes\\\\com\\\\urbanalab\\\\modelo\\\\PersonaDAOJPAImpl.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: entityManagerFactory or jpaTemplate is required
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:84)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304)
… 24 more
Caused by: java.lang.IllegalArgumentException: entityManagerFactory or jpaTemplate is required
at org.springframework.orm.jpa.support.JpaDaoSupport.checkDaoConfig(JpaDaoSupport.java:120)
at org.springframework.dao.support.DaoSupport.afterPropertiesSet(DaoSupport.java:44)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
… 37 more
Simplemente excelente estimado Rubén, tiene la esencia de la solución.
Hola Rubén, felicidades, son muy buenas estas clases, espero que sigan ilustrandonos… Bueno, la implementacion de todo este codigo esta perfectamente, obviamente tambien a mi me vinieron errores, pero uno de los trabajos del programador es resolver los problemas que se presentan… Yo he resuelto modificando una dependencia en el pom.xml.
Se debe sostituir la dependencia persistence-api-1.0.2 por hibernate-jpa-2.0-api, dejo el fragmento del pom con la modifica… Saludos y gracias 😉
CODIGO DE ELIMINAR O COMENTAR
javax.persistence
persistence-api
1.0.2
DEPENDENCIA QUE SOSTITUYE LA ANTERIOR
org.hibernate.javax.persistence
hibernate-jpa-2.0-api
1.0.1.Final
Hola Rubén, felicidades, son muy buenas estas clases, espero que sigan ilustrandonos… Bueno, la implementacion de todo este codigo esta perfectamente, obviamente tambien a mi me vinieron errores, pero uno de los trabajos del programador es resolver los problemas que se presentan… Yo he resuelto modificando una dependencia en el pom.xml.
Se debe sostituir la dependencia persistence-api-1.0.2 por hibernate-jpa-2.0-api, dejo el fragmento del pom con la modifica… Saludos y gracias 😉
CODIGO DE ELIMINAR O COMENTAR
groupId: javax.persistence
artifactId: persistence-api
version: 1.0.2
DEPENDENCIA QUE SOSTITUYE LA ANTERIOR
groupId: org.hibernate.javax.persistence
artifactId: hibernate-jpa-2.0-api
version: 1.0.1.Final
Hola,
Primero agredecer el tuto, está muy bastante clarito todo. Pero tengo el mismo problema que otros tantos aquí al lanzar el test y es que el contexto no se levanta correctamente y no se llega a inicializar el persistenceContext.
¿Alguna luz que arrojar sobre esto? Está todo ok según parece. Pongo el stack trace:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:308)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:333)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:220)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:301)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:303)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name \\\’TaskDAO\\\’ defined in file [D:\\\\DEVEL\\\\git\\\\common-gateway\\\\persistence\\\\target\\\\classes\\\\eu\\\\ohim\\\\cfportal\\\\dao\\\\imp\\\\jpa\\\\TaskDAOJPAImpl.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: entityManagerFactory or jpaTemplate is required
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:84)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304)
… 24 more
Caused by: java.lang.IllegalArgumentException: entityManagerFactory or jpaTemplate is required
at org.springframework.orm.jpa.support.JpaDaoSupport.checkDaoConfig(JpaDaoSupport.java:120)
at org.springframework.dao.support.DaoSupport.afterPropertiesSet(DaoSupport.java:44)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
… 37 more
Buenas,
Hice una prueba con un código pero me ha errores las lineas:
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
Alguien me puede ayudar, parece que no localiza estas importaciones de clases.
Un saludo;
David