LABORATORIO
Objetivos:
·
Configurar
Hibernate 3.
·
Usar la API de
persistencia JPA
·
Configurar Hibernate
como implementación de JPA.
·
Utilizar la
librería JUnit para ejecutar los test de la capa de persistencia.
Equipos, Materiales, Programas y Recursos:
·
PC con Sistema Operativo con soporte a Java.
·
IDE para Java
·
Navegador Web (recomendable Firefox)
·
Contenedor de Servlets (recomendable Tomcat)
·
Spring Framework
·
Hibernate
·
JUnit
Introducción:
En
la presente sesión, se detalla el uso de la API de persistencia JPA.
Procedimiento y Resultados:
Modelo entidad relación
Ejercicio 1: Crear
clases entidad JPA
- Crear un proyecto JPA Project, configurando a su vez la conexión a la base de datos.
- En el paquete src crear las clases entidad JPA (New > Entities from Tables), indicando el paquete proyecto.dao.
- Verá que se han creado varias clases .java y además un archivo llamado persistence.xml.
- Copiaremos las clases .java y el persistence.xml al proyecto Web que se realizó en el laboratorio anterior.
Ejercicio 2:
Puesta en marcha de JPA
- El archivo persistence.xml debe ubicarse en la carpeta /WEB-INF/classes/META-INF/ . Configurarlo de la siguiente manera:
<?xml version="1.0" encoding="UTF-8"?>
<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="tiendaPersistencia"
transaction-type="RESOURCE_LOCAL">
<class>proyecto.modelo.Categoria</class>
<class>proyecto.modelo.DetallePedido</class>
<class>proyecto.modelo.DetallePedidoPK</class>
<class>proyecto.modelo.Pedido</class>
<class>proyecto.modelo.Producto</class>
<class>proyecto.modelo.Rol</class>
<class>proyecto.modelo.Usuario</class>
</persistence-unit>
</persistence>
- Los archivos .java del paquete proyecto.modelo deben ser reemplazados en su totalidad. Revisar las clases y sus anotaciones:
@Entity
@Table
@Id
@Column
@OneToMany
@ManyToOne
@EmbeddedId
@JoinColumn
@ManyToMany
- Configurar el applicationContext.xml:
<?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:aop="http://www.springframework.org/schema/aop"
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/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
http://www.springframework.org/schema/aop
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property
name="persistenceUnitName" value="tiendaPersistencia" />
<property
name="dataSource" ref="dataSource" />
<property
name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property
name="showSql" value="false" />
<property
name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"
/>
</bean>
</property>
</bean>
<!-- the
PlatformTransactionManager, could be DataSourceTransactionManager,
JtaTransactionManager -->
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property
name="entityManagerFactory" ref="entityManagerFactory"
/>
<property
name="dataSource" ref="dataSource"></property>
</bean>
<!-- the transactional advice
(what 'happens'; see the <aop:advisor/> bean below) -->
<tx:advice id="txAdvice"
transaction-manager="transactionManager">
<tx:attributes>
<!-- all
methods starting with 'get' are read-only -->
<tx:method
name="get*" read-only="true" />
<!-- other
methods use the default transaction settings (see below) -->
<tx:method
name="*" />
</tx:attributes>
</tx:advice>
<!-- ensure that transactional
advice runs for any execution of
an operation defined by :
-->
<aop:config>
<aop:advisor
id="managerTx" advice-ref="txAdvice"
pointcut="execution(*
proyecto.service.*Impl.*(..))" />
</aop:config>
<!-- Enables interpretation of
the @PersistenceUnit/@PersistenceContext
annotations providing
convenient access to EntityManagerFactory/EntityManager -->
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
<property
name="defaultPersistenceUnitName"
value="tiendaPersistencia" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property
name="url">
<value>jdbc:mysql://localhost:3306/tienda?autoReconnect=true</value>
</property>
<property
name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property
name="username">
<value>root</value>
</property>
<property
name="password">
<value></value>
</property>
</bean>
… <!- - DAO - - >
…
Notemos que se agregaron los siguientes beans:
- entityManagerFactory
- transactionManager
- dataSource
Además se han agregado otros bloques de código XML que se deben
revisar.
- Modificar el archivo RolDAOImpl:
package
proyecto.dao;
import
java.util.ArrayList;
import
java.util.Collection;
import
javax.persistence.EntityManager;
import
javax.persistence.PersistenceContext;
import
javax.persistence.Query;
import
org.springframework.jdbc.core.JdbcTemplate;
import
proyecto.excepcion.DAOExcepcion;
import
proyecto.modelo.Rol;
public class
RolDAOImpl extends BaseDAO implements RolDAO {
private JdbcTemplate jdbcTemplate;
@PersistenceContext
private EntityManager em;
public void setEm(EntityManager em)
{
this.em = em;
}
public void
setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate =
jdbcTemplate;
}
@SuppressWarnings(value="unchecked")
public Collection<Rol> listar()
throws DAOExcepcion {
Collection<Rol>
entities = new ArrayList<Rol>();
try {
Query
q = em.createNamedQuery("Rol.findAll");
entities = q.getResultList();
} catch (Exception e) {
throw new
DAOExcepcion(e.getMessage());
}
return entities;
}
@SuppressWarnings("unchecked")
public Collection<Rol> buscarPorNombre(String
nombre) throws DAOExcepcion {
Query q =
em.createQuery("select r from Rol r where upper(r.rolNombre) like :nombre
");
q.setParameter("nombre",
"%"+ nombre.toUpperCase() +"%");
return
q.getResultList();
}
public void insertar(Rol vo)
throws DAOExcepcion {
try {
em.persist(vo);
} catch (Exception e) {
e.printStackTrace();
throw new
DAOExcepcion(e.getMessage());
}
}
public Rol obtener(String
rolNombre) throws DAOExcepcion {
try {
return
em.find(Rol.class, rolNombre);
} catch (Exception e) {
throw new
DAOExcepcion(e.getMessage());
}
}
public void eliminar(String
rolNombre) throws DAOExcepcion {
try {
Rol r =
em.find(Rol.class, rolNombre);
em.remove(r);
} catch (Exception
e) {
throw new
DAOExcepcion(e.getMessage());
}
}
public void actualizar(Rol
vo) throws DAOExcepcion {
try {
em.merge(vo);
} catch (Exception e) {
throw new
DAOExcepcion(e.getMessage());
}
}
}
Como se observa, el método listar requiere configurar en el Rol.java la
siguiente línea:
@NamedQueries({@NamedQuery(name
= "Rol.findAll", query = "SELECT r FROM Rol r")})
Esta anotación va encima de la clase Rol
- Vamos a crear una Clase de Pruebas. Crear el paquete proyecto.dao.test y allí crear la clase RolDAOImplTest:
package
proyecto.dao.test;
import static
org.junit.Assert.assertTrue;
import static
org.junit.Assert.fail;
import
java.util.Collection;
import
java.util.HashSet;
import org.junit.Test;
import
org.junit.runner.RunWith;
import
org.springframework.beans.factory.annotation.Autowired;
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 proyecto.dao.RolDAOImpl;
import proyecto.excepcion.DAOExcepcion;
import proyecto.modelo.Rol;
import proyecto.modelo.Usuario;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations
= { "/applicationContext.xml" })
@TransactionConfiguration(transactionManager
= "transactionManager", defaultRollback = false)
@Transactional
public class
RolDAOImplTest {
@Autowired
private RolDAOImpl rolDAOImpl;
@Test
public void testListar() {
try {
Collection<Rol>
roles = rolDAOImpl.listar();
for (Rol rol
: roles) {
System.out.println(rol.getRolNombre());
}
assertTrue(roles.size()
> 0);
} catch (DAOExcepcion e)
{
fail("Error:" + e.getMessage());
}
}
}
Vamos a agregar otros métodos más de prueba:
@Test
public void
testBuscarPorNombre() {
try {
Collection<Rol>
roles = rolDAOImpl.buscarPorNombre("ven");
for (Rol rol
: roles) {
System.out.println(rol.getRolNombre());
for (Usuario u : rol.getUsuarios()) {
System.out.println(u.getNombres());
}
}
assertTrue(roles.size()
> 0);
} catch (DAOExcepcion e)
{
fail("Error:"
+ e.getMessage());
}
}
@Test
public void testInsertar(){
Rol vo = new Rol();
vo.setRolNombre("admin");
vo.setDescripcion("admin");
Usuario u1
= new Usuario();
u1.setIdUsuario("demo1");
HashSet<Usuario>
usuarios = new HashSet<Usuario>();
usuarios.add(u1);
vo.setUsuarios(usuarios);
try {
rolDAOImpl.insertar(vo);
} catch
(DAOExcepcion e) {
fail("Error:"
+ e.getMessage());
}
}
@Test
public void testObtener(){
try {
Rol x =
rolDAOImpl.obtener("admin");
System.out.println(x.getDescripcion());
assertTrue(x.getDescripcion().equals("rol
de admin"));
} catch (DAOExcepcion e)
{
fail("Error:" + e.getMessage());
}
}
@Test
public void
testEliminar(){
try {
rolDAOImpl.eliminar("1111111111");
} catch
(DAOExcepcion e) {
fail("Error:"
+ e.getMessage());
}
}
@Test
public void testActualizar(){
Rol vo = new Rol();
vo.setRolNombre("admin");
vo.setDescripcion("rol
de admin");
Usuario u1
= new Usuario();
u1.setIdUsuario("david");
HashSet<Usuario>
usuarios = new HashSet<Usuario>();
usuarios.add(u1);
vo.setUsuarios(usuarios);
try {
rolDAOImpl.actualizar(vo);
} catch
(DAOExcepcion e) {
fail("Error:"
+ e.getMessage());
}
}
Conclusiones:
En
la presente sesión, se detalló el uso de la librería de persistencia JPA.