(http://sobrejava.com/autor/carlos.quijano)
Publicado last month
Por Carlos Quijano (http://sobrejava.com/autor/carlos.quijano)
Tweet 0 19 1
Ejemplo de DAO genérico con JPA
Ejemplo de DAO genérico con JPA
En este ejemplo se muestra como utilizar el Patrón de DAO
(http://www.oracle.com/technetwork/java/dataaccessobject-138824.html) utilizando JPA para
crear un modelo de acceso datos genérico para la gestión de entidades de una manera
centralizada y efectiva, para ello vamos a necesitar y realizar los siguientes
Pre-requisitos
1. Java 5 o superior
2. NetBeans IDE 7 o superior
3. Esquema de Base de Datos En este ejemplo se utiliza el esquema APP de Derby el cual
ya esta integrado como servicio en NetBeans 7.
Pasos
1. Crear un proyecto utilizando NetBeans IDE y Apache Maven.
2. Crear una Interfase Base (BaseGenericDAO).
3. Crear una Implementación Abstracta (AbstractBaseGenericDAOImpl) que implemente la
interfase BaseGenericDAO.
4. Crear un DAO Concreto que extienda AbstractBaseDAOImpl para persistir una entidad
Evento.
5. Crear una Unidad de Persistencia de pruebas y su respectiva Prueba Unitaria
El código fuente del proyecto puede ser explorado en el https://github.com/carlosquijano/generic-
dao (https://github.com/carlosquijano/generic-dao) y/o descargado directamente aquí
https://github.com/carlosquijano/generic-dao/archive/master.zip
(https://github.com/carlosquijano/generic-dao/archive/master.zip).
1. Crear un nuevo Proyecto con NetBeans y Maven
En este ejemplo vamos a utilizar NetBeans 7.3 para crear un nuevo proyecto utilizando
Maven para gestionar los perfiles y dependencias del proyecto, para iniciar seleccionamos
la siguiente opción de menú
Menu > File > New Project > Maven > Java Application
Etiquetas
wlst (/tag/wlst/), weblogic
(/tag/weblogic/), web (/tag/web/), unity
(/tag/unity/), top (/tag/top/), social (/tag/social/),
sha (/tag/sha/), rmi (/tag/rmi/), referencia
(/tag/referencia/), redhat (/tag/redhat/), oracle
(/tag/oracle/), maven (/tag/maven/),login (/tag/login/), linux (/tag/linux/), libros
(/tag/libros/), juegos (/tag/juegos/), jsf (/tag/jsf/),
jrockit (/tag/jrockit/), jpa (/tag/jpa/), jee
(/tag/jee/), jdeveloper (/tag/jdeveloper/),
jdbc (/tag/jdbc/), intro (/tag/intro/), instalar
(/tag/instalar/), hash (/tag/hash/), facebook
(/tag/facebook/), exceptions (/tag/exceptions/), ejb
(/tag/ejb/), eclipse-link (/tag/eclipse-link/), config
(/tag/config/), commons (/tag/commons/),
android (/tag/android/), 11g (/tag/11g/), 10g
(/tag/10g/),
Popular
Ejemplo de DAO genérico con JPA (http://sobrejava.…
Top 5 Libros Sobre Java (http://sobrejava.com/articu…
Autenticación a Facebook Utilizando Java (http://sob…
Top 5 Librerías y Componentes JSF (http://sobrejav…
Configurar JRockit como JVM Alternativa en Oracle L…
(http://sobrejava.com/)
Java SE (http://sobrejava.com/categoria/java-se) Java EE (http://sobrejava.com/categoria/java-ee) Oracle (http://sobrejava.com/categoria/oracle)
Spring (http://sobrejava.com/categoria/spring) JPA (http://sobrejava.com/categoria/jpa) JSF (http://sobrejava.com/categoria/jsf)
Android (http://sobrejava.com/categoria/android) Otros (http://sobrejava.com/categoria/otros)
Anuncios Google ► Maven Java ► Java Build ► Java Spring ► Java plugin
En la pantalla de configuración del proyecto ingresamos datos tales como nombre,
ubicación, arquetipo, grupo, versión y paquete del proyecto.
Utilizando el archivo POM vamos a importar las dependencias necesarias en un perfil que
nos permita "cambiar" de implementaciones en algún momento dado, en este ejemplo
vamos a utilizar JPA 2.1 con Eclipse Link 2.5, jUnit 4 y Apache Derby respectivamente,
para ello utilizaremos un POM como el siguiente
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://ww
w.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apac
he.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sobrejava.jee</groupId>
<artifactId>generic-dao</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>GenericDAO</name>
<url>http://www.sobrejava.com/articulos/ejemplo-de-dao-generico-con
-jpa</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncodi
ng>
</properties>
<profiles>
<profile>
<id>jpa-eclipselink</id>
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId
>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>10.10.1.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Notar que el POM hace uso de perfiles, es decir, que las depedencias serán
descargadas/utilizadas según el perfil. Es posible crear otro perfil que utilize
Hibernate por ejemplo.
Ahora informamos a NetBeans IDE que utilize el perfil jpa-eclipselink , para ello es
necesario seleccionarlo del menu contextual Set Configuration del proyecto (Click Derecho)
Menu Contextual Proyecto > Set Configuration > jpa-eclipselink
2. Interfase Base
Una vez configurado el proyecto, iniciaremos el desarrollo de la interfase BaseGenericDAO
la cual se utilizara genéricamente para las operaciones CRUD (Create, Update, Delete) de
las entidades a persistir con JPA.
BaseGenericDAO.java
package com.sobrejava.javaee.dao;
import java.io.Serializable;
public interface BaseGenericDAO<T, K extends Serializable> {
T create(T entity);
T update(T entity);
void delete(T entity);
T findById(K key);
}
Notar que la interfase hace uso de tipos genéricos <T, K>, donde "T" representa
la entidad a persistir y "K" el tipo de la llave primaria de la entidad. De esta
manera se "generaliza" el uso de la interfase para casi cualquier entidad.
3. Implementación Abstracta
Tomando en cuenta que BaseDAO es una interfase y que debe de ser implementada para
darle funcionalidad, creamos una nueva clase abstracta AbstractBaseGenericDAOImpl que
implemente los métodos definidos en BaseDAO utilizando JPA como motor de
persistencia.
AbstractBaseGenericDAOImpl.java
package com.sobrejava.javaee.dao.jpa;
import com.sobrejava.javaee.dao.BaseGenericDAO;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
public abstract class AbstractBaseGenericDAOImpl<T, K extends Serializa
ble> implements BaseGenericDAO<T, K> {
@PersistenceContext
protected EntityManager em;
protected Class<T> classType;
public AbstractBaseGenericDAOImpl() {
super();
this.classType = (Class<T>)getParameterClass(getClass(), 0);
}
@Override
public T create(T entity) {
this.em.persist(entity);
return entity;
}
@Override
public T update(T entity) {
return this.em.merge(entity);
}
@Override
public void delete(T entity) {
this.em.remove(entity);
}
@Override
public T findById(K key) {
return this.em.find(classType, key);
}
private static Class<?> getParameterClass(Class<?> clazz, int index
) {
return (Class<?>)(((ParameterizedType)clazz.getGenericSuperclas
s()).getActualTypeArguments()[index]);
}
}
Lo único especial a notar en la clase AbstractBaseGenericDAOImpl es el uso
del método privado getParameterClass el cual se utiliza para obtener el tipo de
objeto de la clase parametrizada K.
4. DAO Concreto
Una vez definida la clase abstracta AbstractBaseGenericDAOImpl es necesario extenderla
en un DAO Concreto es decir en un DAO con sentido ya orientado a una entidad en
específico, en este ejemplo, vamos a crear un DAO que persista una entidad Evento la
cual es la representación de una tabla APP.EVENTS en el esquema APP del Derby
integrado de NetBeans.
Evento.java
package com.sobrejava.javaee.eventos.model;
import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "EVENTS")
public class Evento implements Serializable {
public static final String SEVERIDAD_INFO = "INFO";
public static final String SEVERIDAD_ERROR = "ERROR";
public static final String SEVERIDAD_DEBUG = "DEBUG";
public static final String SEVERIDAD_FATAL = "FATAL";
@Id
@Column(name = "EVENT_ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long eventoId;
@Column(name = "SEVERITY", length = 32)
private String severidad;
@Column(name = "MESSAGE", length = 512)
private String mensaje;
@Column(name = "STAMP")
private Timestamp fecha;
public Long getEventoId() {
return eventoId;
}
public void setEventoId(Long eventoId) {
this.eventoId = eventoId;
}
public String getSeveridad() {
return severidad;
}
public void setSeveridad(String severidad) {
this.severidad = severidad;
}
public String getMensaje() {
return mensaje;
}
public void setMensaje(String mensaje) {
this.mensaje = mensaje;
}
public Timestamp getFecha() {
return fecha;
}
public void setFecha(Timestamp fecha) {
this.fecha = fecha;
}
}
EventoDAO.java
package com.sobrejava.javaee.eventos.dao;
import com.sobrejava.javaee.dao.BaseGenericDAO;
import com.sobrejava.javaee.eventos.model.Evento;
public interface EventoDao extends BaseGenericDAO<Evento, Long> {
}
EventoDAOImpl.java
package com.sobrejava.javaee.eventos.dao.jpa;
import com.sobrejava.javaee.dao.jpa.AbstractBaseGenericDAOImpl;
import com.sobrejava.javaee.eventos.dao.EventoDao;
import com.sobrejava.javaee.eventos.model.Evento;
public class EventoDaoImpl extends AbstractBaseGenericDAOImpl<Evento, L
ong> implements EventoDao {
}
Notar que la interfase EventoDAO extiende a BaseGenericDAO tipificandola con
la entidad Evento y Long, es decir, es un DAO concreto para la entidad Evento
y su llave primaria del tipo Long. Asimismo la implementación JPA de dicha
interfase EventoDAOImpl extiende a AbstractBaseGenericDAOImpl la cual
hereda su funcionalidad.
5. Unidad de Persistencia y Prueba Unitaria
Finalmente vamos a crear una unidad de persistencia (Persistence Unit) de pruebas y una
prueba unitaria con jUnit para probar el EventoDAO.
META-INF/persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persisten
ce" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLoc
ation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml
/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="pu-generic-dao-test" transaction-type="RESOUR
CE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider
>
<class>com.sobrejava.javaee.eventos.model.Evento</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:derby://l
ocalhost:1527/sample"/>
<property name="javax.persistence.jdbc.password" value="app"/>
<property name="javax.persistence.jdbc.driver" value="org.apache.
derby.jdbc.ClientDriver"/>
<property name="javax.persistence.jdbc.user" value="app"/>
<property name="eclipselink.ddl-generation" value="create-tables"
/>
</properties>
</persistence-unit>
</persistence>
EventoDAOTest.java
package com.sobrejava.dao;
import com.sobrejava.javaee.eventos.model.Evento;
import java.sql.Timestamp;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class EventoDaoTest {
String pu = "pu-generic-dao-test";
EntityManager em;
EntityManagerFactory emf;
@Before
public void before() {
this.emf = Persistence.createEntityManagerFactory(pu);
this.em = emf.createEntityManager();
}
@Test
public void testSaveEvents() {
Assert.assertNotNull(em);
Timestamp stamp;
EntityTransaction trx = null;
try {
trx = em.getTransaction();
stamp = new Timestamp(System.currentTimeMillis());
Evento evento = new Evento();
evento.setFecha(stamp);
evento.setMensaje("Este es un mensaje generado en " + stamp
);
evento.setSeveridad(Evento.SEVERIDAD_INFO);
trx.begin();
em.persist(evento);
trx.commit();
} catch (RuntimeException e) {
if (trx != null && trx.isActive()) {
trx.rollback();
}
}
}
@After
public void after() {
em.close();
emf.close();
}
}
Notar que es antes de ejecutar la prueba unitaria es necesario iniciar la base
de datos
Al ejecutar la prueba unitaria, de no existir problemas se puede observar algo similar a lo
siguiente:
APP.EVENTS
jee (/tag/jee) jpa (/tag/jpa) eclipse-link (/tag/eclipse-link)
Conclusiones
Con la estrategia anterior es posible generar un DAO para cada entidad, prácticamente copiando
y pegando las 3 clases anteriores (Evento, EventoDAO, EventoDAOImpl) y aunque exista cierto
grado de trabajo, el nivel de flexibilidad que se obtiene es de gran escala, ya que podemos
extender e implementar más métodos tales como count, findAll, findBy, etc. utilizando las
mismas clases dependiendo de la necesidad de una manera simple, elegante y fácil de entender.
Referencias
1. Core J2EE Patterns - Data Access Object
http://www.oracle.com/technetwork/java/dataaccessobject-138824.html
(http://www.oracle.com/technetwork/java/dataaccessobject-138824.html)
Tags
0 comentarios
Deja un comentario...
Mejor Comunidad ⚙ ⤤Compartir
Nadie ha comentado aún.
Canal de com entariosr Sus críbete por e-m ai l✉
0★
Inicio (http://sobrejava.com/) · Acerca de (http://sobrejava.com/acerca-de) · Contacto
(http://sobrejava.com/contacto)
Copyright © 2013 SobreJava.com. Carlos Quijano. Todos los derechos reservados.
Marcas Registradas como Java y Oracle son propiedad de Oracle Corportation y/o sus respectivos
propietarios intelectuales.
Anuncios Google ► Java plugin ► Java JPA ► Java IDE ► Java Jquery
Top Related