Aplicación standAlone JPA + Hibernate +Maven en Español !


En este post se explicará paso a paso como crear una aplicación Stand alone que accede a una base de datos Mysql utilizando la implementación de Hibernate para JPA.

Configuración

El primer paso es definir las dependencias a utilizar en el proyecto, para este caso se utilizarán las siguientes:

<dependencies>
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-entitymanager</artifactId>
		<version>5.2.3.Final</version>
	</dependency>

	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.3</version>
	</dependency>
</dependencies>

Las dependencias a utilizar son :

  • hibernate-entitymanager : Implementación de Hibernate para JPA
  • mysql-connector-java : Driver de MySQL (Puede variar dependiendo del manejador a utilizar)

Definir tablas a utilizar, en este ejemplo se utilizará solo una tabla llamada USER:

CREATE TABLE USER(
USER_ID INTEGER PRIMARY KEY AUTO_INCREMENT,
USERNAME VARCHAR(100) NOT NULL,
PASSWORD VARCHAR(100) NOT NULL
);

Una vez definidas las dependencias y la tabla a utilizar se debe crear el archivo de configuración más importante en JPA este es el archivo persistence.xml y se debe colocar en el folder META-INF dentro de la carpeta src/main/resources. La estructura quedaría del siguiente modo src/main/resources/META-INF/persistence.xml con lo siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 	xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
	<persistence-unit name="MyPersistenceUnit" 		transaction-type="RESOURCE_LOCAL">
		<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

		<class>com.raidentrance.entities.User</class>
		<properties>
			<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
			<property name="javax.persistence.jdbc.url" 				value="jdbc:mysql://localhost:3306/jpaexample?zeroDateTimeBehavior=convertToNull" />
			<property name="javax.persistence.jdbc.user" value="root" />
			<property name="javax.persistence.jdbc.password" value="root" />
		</properties>
	</persistence-unit>
</persistence>

Crear entidad a utilizar

JPA es un framework ORM, por esto es necesario definir una entidad Java que represente la tabla que se utiliza en la base de datos.

/**
 *
 */
package com.raidentrance.entities;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * @author raidentrance
 *
 */
@Entity
@Table(name = "USER")
public class User implements Serializable {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "USER_ID")
	private Integer userId;

	@Column(name = "USERNAME")
	private String username;

	@Column(name = "PASSWORD")
	private String password;

	private static final long serialVersionUID = -1382782006959182944L;

	public User() {
	}

	public User(String username, String password) {
		super();
		this.username = username;
		this.password = password;
	}

	public User(Integer userId, String username, String password) {
		this.userId = userId;
		this.username = username;
		this.password = password;
	}

	public Integer getUserId() {
		return userId;
	}

	public void setUserId(Integer userId) {
		this.userId = userId;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((userId == null) ? 0 : userId.hashCode());
		result = prime * result + ((username == null) ? 0 : username.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (userId == null) {
			if (other.userId != null)
				return false;
		} else if (!userId.equals(other.userId))
			return false;
		if (username == null) {
			if (other.username != null)
				return false;
		} else if (!username.equals(other.username))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "User [userId=" + userId + ", username=" + username + "]";
	}

}
  • Por cada campo definido en la base de datos existe un campo definido en la entidad JPA que lo representa con esto cuando se realice una consulta en lugar de recibir un ResultSet como en Jdbc recibiremos un List lo cual facilitará el desarrollo.

Creando un contexto para la aplicación

Como este ejemplo no depende de Spring la aplicación debe ser capaz de crear los objetos y administrarlo.

/**
 *
 */
package com.raidentrance.util;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

/**
 * @author raidentrance
 *
 */
public class ApplicationContext {

	private EntityManagerFactory entityManagerFactory;

	private static ApplicationContext instance = new ApplicationContext();

	private ApplicationContext() {
		entityManagerFactory = Persistence.createEntityManagerFactory("MyPersistenceUnit");
	}

	public static ApplicationContext getInstance() {
		return instance;
	}

	public EntityManager getEntityManager() {
		return entityManagerFactory.createEntityManager();
	}

	public void closeEntityManager() {
		entityManagerFactory.close();
	}

}

Como se puede observar  este contexto sigue el patron de diseño Singleton y es responsable de crear un EntityManagerFactory e instancias de EntityManager.

El objeto EntityManager será el responsable de acceder a la base de datos, crear las consultas sql, traducir las respuestas a objetos java, entre otras cosas.

Creando un DAO abstracto

DAO es un patrón de diseño que significa ( Data access object ) el cual es una interfaz de acceso a una base de datos en una aplicación. En este ejemplo se creará un DAO abstracto el cuál definirá acciones comunes CRUD (Create, read, update y delete). Con esto las implementaciones de este ya no tendrán que reescribir código para estas acciones comunes.

/**
 *
 */
package com.raidentrance.dao;

/**
 * @author raidentrance
 *
 */
import java.util.List;

import javax.persistence.EntityManager;

public abstract class AbstractFacade<T> {

	private final Class<T> entityClass;
	private EntityManager entityManager;

	public AbstractFacade(Class<T> entityClass, EntityManager entityManager) {
		this.entityClass = entityClass;
		this.entityManager = entityManager;
	}

	protected EntityManager getEntityManager() {
		return entityManager;
	}

	public void create(T entity) {
		getEntityManager().getTransaction().begin();
		getEntityManager().persist(entity);
		getEntityManager().getTransaction().commit();
	}

	public void edit(T entity) {
		getEntityManager().getTransaction().begin();
		getEntityManager().merge(entity);
		getEntityManager().getTransaction().commit();
	}

	public void remove(T entity) {
		getEntityManager().getTransaction().begin();
		T find = getEntityManager().find(entityClass, entity);
		getEntityManager().remove(find);
		getEntityManager().getTransaction().commit();
	}

	public T find(Object id) {
		return getEntityManager().find(entityClass, id);
	}

	public List<T> findAll() {
		javax.persistence.criteria.CriteriaQuery<T> cq = getEntityManager().getCriteriaBuilder()
				.createQuery(entityClass);
		cq.select(cq.from(entityClass));
		return getEntityManager().createQuery(cq).getResultList();
	}

	public void close() {
		entityManager.close();
	}
}

Como se puede observar, en lugar de utilizar alguna entidad en específico se define un dato genérico que será definido en la clase hija.

Creando DAO para usuarios

El siguiente paso es crear un DAO específico para la clase Usuario que es la entidad que se creó para este ejemplo. En esta clase ya no se deben implementar todas las acciones CRUD ya que estas ya se encuentran definidas en el DAO abstracto.

/**
 *
 */
package com.raidentrance.dao;

import javax.persistence.EntityManager;

import com.raidentrance.entities.User;

/**
 * @author raidentrance
 *
 */
public class UserDao extends AbstractFacade<User> {

	public UserDao(EntityManager entityManager) {
		super(User.class, entityManager);
	}

}

Lo bueno de este tipo de patrón es que si se necesita crear 100 entidades, no es necesario reescribir el código para las operaciones CRUD para todos, solo es necesario heredar de el DAO abstracto.

Ejecutar la aplicación

El último paso es crear la clase principal utilizará todos los componentes creados para persistir objetos de tipo usuario y para obtenerlos de la base de datos.

/**
 *
 */
package com.raidentrance;

import java.util.List;
import java.util.Random;
import java.util.logging.Logger;

import javax.persistence.EntityManager;

import com.raidentrance.dao.UserDao;
import com.raidentrance.entities.User;
import com.raidentrance.util.ApplicationContext;

/**
 * @author raidentrance
 *
 */
public class JpaApplication {
	private static final Logger log = Logger.getLogger(JpaApplication.class.getName());

	public static void main(String[] args) {
		ApplicationContext context = ApplicationContext.getInstance();
		EntityManager entityManager = context.getEntityManager();

		UserDao dao = new UserDao(entityManager);

		User userEntity = new User("raidentrance ".concat(new Integer(new Random(100).nextInt()).toString()), "López");
		dao.create(userEntity);

		List<User> list = dao.findAll();
		for (User user : list) {
			log.info(user.toString());
		}

		dao.close();
		context.closeEntityManager();
	}
}

Conclusión

En este ejemplo se explica como acceder a una base de datos utilizando JPA sin depender de otros frameworks como Spring data, Spring Hibernate, etc. Sólo se utiliza la implementación de Hibernate de JPA, el driver de Jdbc de MySQL y patrones de diseño como AbstractFacade, DAO y Singleton.

Puedes encontrar el código completo del ejemplo en el siguiente enlace:

https://github.com/raidentrance/jpa-example

Autor: Alejandro Agapito Bautista

Twitter: @raidentrance

Contacto:raidentrance@gmail.com

Anuncios

1 comentario »

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s