miércoles, 1 de septiembre de 2010

Spring Framework, Hibernate y Maven en 4 pasos

Spring Framework, Hibernate y Maven en 4 pasos

SPRING FRAMEWORK

Para este ejemplo estoy usando Ubuntu 10.04, Maven y una base de datos MySQL con el esquema test.

Creamos un schema en la base de datos con un tabla:
create database ejemplo;
use ejemplo;
create table producto(
id int not null,
nombre varchar(20),
valor double,
PRIMARY KEY(id));


https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=7089-jta-1.0.1B-mr-class-oth-JSpec@CDS-CDS_Developer

mvn install:install-file -Dfile=jta-1_0_1B-classes.zip -DgroupId=javax.transaction -DartifactId=jta -Dversion=1.0.1B -Dpackaging=jar

Paso 1) Creación y Configuración de proyecto de Maven

Creacion de proyecto Maven
mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.ejemplo -DartifactId=proyecto1

Luego abrimos pom.xml y agregamos dependencias, repositories y plugins a nuestro archivo de configuracion de maven de tal manera que quede de la siguiente manera

<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.ejemplo</groupId>
<artifactId>proyecto1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>proyecto1</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>JBoss repository</id>
<url>http://repository.jboss.com/maven2/</url>
</repository>
<repository>
<id>Java.Net</id>
<url>http://download.java.net/maven/2/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>2.5.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>2.5.5</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<dependency>
<groupId>hibernate</groupId>
<artifactId>hibernate3</artifactId>
<version>3.2.3.GA</version>
</dependency>
<dependency>
<groupId>hibernate-annotations</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.3.0.GA</version>
</dependency>
<dependency>
<groupId>hibernate-commons-annotations</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>3.0.0.GA</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>antlr</groupId>
<artifactId>antlr</artifactId>
<version>2.7.7</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
</project>

Luego ejecutamos mvn clean install



mkdir -p src/main/java/com/ejemplo/negocio/model
mkdir -p src/main/java/com/ejemplo/negocio/util
mkdir -p src/main/java/com/ejemplo/negocio/dao
mkdir -p src/main/java/com/ejemplo/negocio/bo
mkdir -p src/main/java/com/ejemplo/negocio/dao/impl
mkdir -p src/main/java/com/ejemplo/negocio/bo/impl
mkdir -p src/main/java/resources

Paso 2)Archivos de configuración del proyecto
En este paso vamos a crear:
- Archivo de propiedades
- DataSource.xml
- Hibernate.xml
- BeanLocations.xml


En el directorio resources de main del proyecto de maven, vamos a crear un archivo de propiedades llamado database.properties, el cual tendrá informacion relacionada a la base de datos a la cual nos vamos a conectar:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ejemplo
jdbc.username=root
jdbc.password=root

Luego creamos un archivo llamado DataSource.xml, el cual tendra información para la fuente de datos de la aplicación, en base al archivo de propiedades antes creado:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>database.properties</value>
</property>
</bean>

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>

</beans>


Una vez hecho esto tenemos que crear el archivo Hibernate.xml, que usará la información de DataSource para la configuración de hibernate.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.ejemplo.negocio.model.Producto</value>
</list>
</property>
</bean>
</beans>


Finalmente, tenemos que crear el archivo BeanLocations.xml para indicarle a Spring como se va a conectar a la base de datos y en que paquetes estan los recursos que usará la aplicación:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<!-- Database Configuration -->
<import resource="DataSource.xml"/>
<import resource="Hibernate.xml"/>

<!-- Auto scan the components -->
<context:component-scan
base-package="com.ejemplo.negocio" />

</beans>

Paso 3) Creacion de clases.
En este paso vamos a crear:
1.Mapeo a la base de datos.
2.Data Access Objects
3.Business Objects


Primeramente debemos crear una clase padre, encargada de utilizar la anotación Autowired.
Creamos el archivo SoporteHibernateDao en la ruta src/main/java/com/ejemplo/negocio/util

package com.ejemplo.negocio.util;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public abstract class SoporteHibernateDao extends HibernateDaoSupport{
@Autowired
public void metodoSoporte(SessionFactory sessionFactory){
setSessionFactory(sessionFactory);
}
}

Luego de hecho esto, vamos a crear una clase utilitaria que nos permita recuperar los beans del contexto de hibernate, esta clase se llama SpringContext y va dentro del archivo SpringContext.java que se encontrará guardado en la ruta:src/main/java/com/ejemplo/negocio/util
package com.ejemplo.negocio.util;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringContext{
private static ApplicationContext contexto;
private static SpringContext instancia;
private final static String ARCHIVO_CONF = "BeanLocations.xml";
public static SpringContext getInstance() {
if (null == instancia) {
instancia = new SpringContext();
contexto = new ClassPathXmlApplicationContext(ARCHIVO_CONF);
}
return instancia;
}

public Object getBean(String nombreBean) {
return contexto.getBean(nombreBean);
}
}


Dentro del directorio src/main/java/com/ejemplo/negocio/model, creamos un archivo con la clase llamada Producto.Esta clase se encuentra mapeada por medio de anotaciones a la tabla producto de la Base de Datos, es decir:

package com.ejmplo.negocio.model;

import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity
@Table(name = "producto")
@NamedQueries({
@NamedQuery(name = "Producto.findAll", query = "SELECT p FROM Producto p"),
@NamedQuery(name = "Producto.findById", query = "SELECT p FROM Producto p WHERE p.id = :id"),
@NamedQuery(name = "Producto.findByNombre", query = "SELECT p FROM Producto p WHERE p.nombre = :nombre"),
@NamedQuery(name = "Producto.findByValor", query = "SELECT p FROM Producto p WHERE p.valor = :valor")})
public class Producto implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Column(name = "nombre")
private String nombre;
@Column(name = "valor")
private Double valor;

public Producto() {
}

public Producto(Integer id, String nombre, Double valor){
this.id=id;
this.nombre=nombre;
this.valor=valor;
}

public Producto(Integer id) {
this.id = id;
}

public Integer getId() {
return id;
}

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

public String getNombre() {
return nombre;
}

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

public Double getValor() {
return valor;
}

public void setValor(Double valor) {
this.valor = valor;
}
}

Una vez hecho esto, debemos crear la interface DAO, para esto creamos el archivo ProductoDao.java en src/main/java/com/ejemplo/negocio/dao, con el siguiente código:
package com.ejemplo.negocio.dao;
import com.ejemplo.negocio.model.Producto;
import java.util.List;

public interface ProductoDao{
void save(Producto producto);
void delete(Producto producto);
Producto findById(Integer id);
List<Producto> findAll();
}


Luego de creado esto, debemos implementar esta interface. Para eso creamos el archivo llamado ProductoDaoImpl.java, en la ruta src/main/java/com/ejemplo/negocio/dao/impl, con el siguiente código:
package com.ejemplo.negocio.dao.impl;
import com.ejemplo.negocio.dao.ProductoDao;
import com.ejemplo.negocio.model.Producto;
import com.ejemplo.negocio.util.SoporteHibernateDao;
import java.util.List;
import org.springframework.stereotype.Repository;

@Repository("productoDao")
public class ProductoDaoImpl extends SoporteHibernateDao implements ProductoDao{
public void save(Producto producto){
getHibernateTemplate().save(producto);
}
public void delete(Producto producto){
getHibernateTemplate().delete(producto);
}
public Producto findById(Integer id){
String[] nombreParametros={"id"};
Object[] parametros={id};
return (Producto)(getHibernateTemplate().findByNamedQueryAndNamedParam("Producto.findById",nombreParametros,parametros).get(0));
}
public List<Producto> findAll(){
return (List<Producto>)getHibernateTemplate().findByNamedQuery("Producto.findAll");
}
}

Hecho, esto tenemos que crear los Business Objects que serán los usados por nuestro cliente:
Primero, creamos el archivo ProductoBo.java en la ruta:src/main/java/com/ejemplo/negocio/bo

package com.ejemplo.negocio.bo;
import com.ejemplo.negocio.model.Producto;
import java.util.List;

public interface ProductoBo{
void guardar(Producto producto);
void eliminar(Producto producto);
Producto recuperarPorId(Integer id);
List<Producto> recuperarTodos();
}


Luego implementamos esta interface en el archivo ProductoBoImpl que se encuentra en la ruta:src/main/java/com/ejemplo/negocio/dao/impl

package com.ejemplo.negocio.bo.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import com.ejemplo.negocio.bo.ProductoBo;
import com.ejemplo.negocio.dao.ProductoDao;
import com.ejemplo.negocio.model.Producto;

@Service("productoBo")
public class ProductoBoImpl implements ProductoBo{
@Autowired
ProductoDao productoDao;

public void setProductoDao(ProductoDao productoDao){
this.productoDao=productoDao;
}

public void guardar(Producto producto){
productoDao.save(producto);
}
public void eliminar(Producto producto){
productoDao.delete(producto);
}
public Producto recuperarPorId(Integer id){
return productoDao.findById(id);
}
public List<Producto> recuperarTodos(){
return productoDao.findAll();
}
}

Paso 4) Creación de cliente

Una vez creadas estas clases, podemos crear un test. Para este ejemplo voy a usar el archivo App.java que se encuentra dentro de:src/test/java/com/ejemplo

package com.ejemplo;

import com.ejemplo.negocio.bo.ProductoBo;
import com.ejemplo.negocio.model.Producto;
import com.ejemplo.negocio.util.SpringContext;

import org.apache.log4j.Logger;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{

private static Logger logger = Logger.getLogger(AppTest.class);

public AppTest( String testName )
{
super( testName );
}

public static Test suite()
{
return new TestSuite( AppTest.class );
}

public void testApp()
{
SpringContext contexto = SpringContext.getInstance();
ProductoBo productoBo=(ProductoBo)contexto.getBean("productoBo");
Producto p=new Producto(1,"jabon",13.00);
productoBo.guardar(p);
Producto p1=productoBo.recuperarPorId(1);
System.out.println("Recuperacion individual:"+p1.getNombre());
for(Producto producto:productoBo.recuperarTodos()){
System.out.println("Recuperacion Lista:"+producto.getNombre());
}
productoBo.eliminar(p);

}
}


Finalmente ejecuto mvn clean:install desde una consola de comandos, tengo la siguiente salida:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.ejemplo.AppTest
Hibernate: insert into producto (nombre, valor, id) values (?, ?, ?)
Hibernate: select producto0_.id as id0_, producto0_.nombre as nombre0_, producto0_.valor as valor0_ from producto producto0_ where producto0_.id=?
Recuperacion individual:jabon
Hibernate: select producto0_.id as id0_, producto0_.nombre as nombre0_, producto0_.valor as valor0_ from producto producto0_
Recuperacion Lista:jabon
Hibernate: select producto_.id, producto_.nombre as nombre0_, producto_.valor as valor0_ from producto producto_ where producto_.id=?
Hibernate: delete from producto where id=?
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.67 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] [jar:jar {execution: default-jar}]
[INFO] Building jar: /home/santiago/proyecto1/target/proyecto1-1.0-SNAPSHOT.jar
[INFO] [install:install {execution: default-install}]
[INFO] Installing /home/santiago/proyecto1/target/proyecto1-1.0-SNAPSHOT.jar to /home/santiago/.m2/repository/com/ejemplo/proyecto1/1.0-SNAPSHOT/proyecto1-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9 seconds
[INFO] Finished at: Wed Sep 01 16:45:40 ECT 2010
[INFO] Final Memory: 21M/154M
[INFO] ------------------------------------------------------------------------

No hay comentarios:

Publicar un comentario