martes, 22 de octubre de 2013

JPA CON HIBERNATE



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


  1. Crear un proyecto JPA Project, configurando a su vez la conexión a la base de datos.

  1. En el paquete src crear las clases entidad JPA (New > Entities from Tables), indicando el paquete proyecto.dao.

  1. Verá que se han creado varias clases .java y además un archivo llamado persistence.xml.

  1. 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


  1. 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>


  1. 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

  1. 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
                       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">


            <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.

  1. 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

 
  1. 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.