Utilizando EJB y JPA

Complementando a los artículos sobre las novedades JavaEE 6 creo que es interesante comentar cuatro lineas de recordatorio del uso de EJB y JPA para la implementación de la lógica de negocio y la persistencia de datos.

Negocio con EJB 3

La capa de negocio de la aplicación (funcionalidad, lógica de negocio, transacciones ...) la implementaremos mediante EJB3 y el mecanismo de Session Beans. Recordemos que dentro de EJB3 también está definido el estándar JPA que utilizamos para la persistencia.De la misma manera que los Entity Bean de JPA se pueden ver como una capa de abstracción por encima de una base de datos a nivel de datos, los Session Bean actúan de encapsulamiento de las transacciones y la lógica de negocio del aplicación. Técnicamente es donde se dan las transacciones de base de datos.

Tipos de Session Bean

Hay tres tipos de session bean: stateless, stateful y message-driven. Los dos primeros son los habituales para implementar la lógica de negocio habitual y la diferencia entre ellos se si tienen estado o no entre llamadas (y entre transacciones de la base de datos). Los stateless son más frecuentes. Los session bean message-driven sirven para implementar lógica de negocio mediante el patrón de paso de mensajes.

Persistencia con JPA

La capa de persistencia la implementaremos mediante la Java Persistence API 1.0 o JPA . JPA forma parte del estándar Enterprise JavaBeans 3.0 o EJB 3 . En próximas revisiones el estándar JPA evolucionará de forma independiente a EJB3.JPA es una herramienta ORM ( Object Relational Mapping ) basada en POJOs ( Plain Old Java Objects ). Esto quiere decir que el diseño y uso del modelo de datos (el dominio) en nuestra aplicación se hará con objetos Java convencionales.

Entidades (POJO Beans)

Como hemos comentado las entidades son POJOs. La única diferencia es que las anotamos. Por ejemplo:

@Entity
public class Client extends Serializable {  
  @Id
  private long id;
  private String nom;

  ... getters/setters para los atributos ...
}
EntityManager

Las entidades cuando se crean son sólo objetos Java (POJOs). No hay relación con la base de datos aún. Decimos que están en modo desconectado. Para manejarla con el estado guardado en la base de datos hay que hacerlo con el EntityManager.El EntityManager es un servicio (una clase de JPA) mediante la cual podemos consultar, actualizar, borrar, etc. entidades (clases de nuestro dominio) de la aplicación.Una vez que una entidad está asociada a un EntityManager todos los cambios realizado sobre la entidad se propagan automáticamente a la bbdd.

PersistenceContext

Un contexto de persistencia es un conjunto de entidades gestionadas por un EntityManager. Normalmente están asociadas a una sola transacción en la bbdd aunque es posible tener unidades de persistencia extendidas.

¿Cómo hacemos una transacción?

El código para las transacciones estará dentro de SessionBeans (ver capa lógica de negocio, EJB3). En estos beans se pone una anotación para obtener el EntityManager y cada método del bean actúa como una transacción . Por ejemplo:

public class ClientControllerBean {  
  @PersistenceContext
  EntityManager em;

  public Client canviNom(int idClient, String nouNom) {
    Client c = em.find(Client.class, idClient);
    c.setNom(nouNom);
    return c;
  }
}
Entidades desconectadas

Una vez fuera de un contexto de persistencia los beans vuelven a ser POJOs sin conexión a la bbdd. Los cambios hechos no se propagan. Pero mantienen los datos y se pueden utilizar en otras capas (vista, JSF, por ejemplo) o serializados y enviados por red.

Unidad de persistencia y persistence.xml

Una unidad de persistencia es un conjunto de clases POJO que queremos gestionar con JPA. Se definen con un archivo persistence.xml . Este fichero puede incluir la definición de las entidades pero en nuestro caso lo hacemos con anotaciones y este archivo está bastante vacío definiendo sólo la conexión a la base de datos.

<?xml version="1.0" encoding="UTF-8"?>  
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">  
 <persistence-unit name="dukesBank">
   <jta-data-source>java:/DukesBankDS</jta-data-source>
   <properties>
     <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/>
     <property name="hibernate.hbm2ddl.auto" value="update"/>
     <property name="hibernate.show_sql" value="true"/>
   </properties>
 </persistence-unit>
</persistence>  
Parámetros de configuración
<provider>

The provider element specifies the name of the persistence provider's javax.persistence.spi.PersistenceProvider class. The provider element must be specified if the application is dependent upon a particular persistence provider being used.

Usa lo que tiene por defecto el contenedor, en el caso de GlassFish, EclipseLink. Pero también puede usar Hibernate.

(The default persistence provider in the GlassFish Server is based on the EclipseLink Java Persistence API implementation. All configuration options in EclipseLink are available to applications that use the GlassFish Server's default persistence provider.)

transaction-type

The transaction-type attribute is used to specify whether the entity managers provided by the entity manager factory for the persistence unit must be JTA entity managers or resource-local entity managers. The value of this element is JTA or RESOURCELOCAL. A transaction-type of JTA assumes that a JTA data source will be provided—either as specified by the jta-data-source element or provided by the container. In general, in Java EE environments, a transaction-type of RESOURCELOCAL assumes that a non-JTA datasource will be provided. In a Java EE environment, if this element is not specified, the default is JTA. In a Java SE environment, if this element is not specified, a default of RESOURCE_LOCAL may be assumed.

Por lo tanto, al definir uno:

<jta-data-source>jdbc/nombrejndi</jta-data-source>

Es implícito que se utiliza transacciones de tipo JTA.