Combinar cadenas(string) de varios registros al estilo SUM del SQL – Mysql y Postgres

Holas,

La necesidad es combinar el resultado de una consulta sql de varios registros sobre una columna tipo string o varchar determinada, en un solo resultado al mismo estilo del usar el SUM() o AVG(), por ejemplo:

select nombre from cliente;

los datos de la tabla son:


ID NOMBRE TIPO
__________ _____________ _______
1 nombreA new
2 nombreB new
3 nombreC old

hacer una consulta que devuelva:


TIPO NOMBRES
_________ ________________
new nombreA;nombreB
old nombreC

para esto existe la función en MySQL GROUP_CONCAT que se aplica algo como:


SELECT tipo, GROUP_CONCAT(nombre SEPARATOR ';') nombres
FROM cliente:
GROUP BY tipo;

Esta función tiene ORDER BY o DISTINCT y la documentación completa esta obviamente en la página de MySQL el problema es que muchos (y me incluyo hasta hace poco) no la conocen.

Les dejo un link que tiene muchas mas información, y además como solventar la misma situación en SQL Server o PostgreSQL:

http://www.postgresonline.com/journal/archives/191-String-Aggregation-in-PostgreSQL,-SQL-Server,-and-MySQL.html

Espero que les sirva y de paso me dejo el TIP
Suerte!!!

BDD Topics, General, Uncategorized , , , , , Leave a comment

Configurar Mysql 5, PHP 5 y Apache 2 en Windows + Joomla

Muchos tutoriales existen de esto pero no muy completos y con vacíos en versiones por citar un caso, por eso les dejo un trabajo que espero les simplifique esta tareas iniciales con las instalaciones de Joomla y mas sus software base

Los pasos son los siguientes

1. Instalo la versión de Apache 2.2 (httpd-2.2.22-win32-x86-no_ssl.msi) normalmente
2. Instalo la versión de PHP 5.2 (php-5.2.17-nts-Win32-VC6-x86.msi Non Thread Safe es la mejor en velocidad para Windows SO), en donde el instalador le preguntará que servidor Web desea configurar, en este caso escogemos el Apache 2.2.x Module; en la siguiente pantalla de extensiones seleccionamos como imprescindibles a mysql y mysqli, y como recomendadas las extensiones útiles en comunes tareas de funcionalidad e integración a los módulos: bzip2, curl, ldap, soap, xml-rpc y zip
3. Pos esta instalación aun necesitamos configurar el HTTP Apache para decirle donde esta el módulo que carga la funcionalidad con PHP y en donde esta el php.ini que determina el comportamiento asociado. Para este fin nos vamos a “c:\<directoriodeinstalaciondelAPACHE>\conf” y abrimos el archivos “httpd.conf” encontrando al final el siguiente texto:

#BEGIN PHP INSTALLER EDITS – REMOVE ONLY ON UNINSTALL
PHPIniDir “”
LoadModule php5_module “php5apache2_2.dll”
#END PHP INSTALLER EDITS – REMOVE ONLY ON UNINSTALL

y cambiamos por:

#BEGIN PHP INSTALLER EDITS – REMOVE ONLY ON UNINSTALL
PHPIniDir “C:\<directoriodeinstalaciondelPHP>”
LoadModule php5_module “C:\<directoriodeinstalaciondelapachePHP>\php5apache2_2.dll”
#END PHP INSTALLER EDITS – REMOVE ONLY ON UNINSTALL

4. IMPRESCINDIBLE REINICIAR WINDOWS, esto debido a que el instalador de PHP modifica las variables de ambiente para ubicar los recursos necesarios, y para que esta configuración tenga efecto deben reiniciar el PC

5. Probamos nuestra configuración creando un pagina test.php en “c:\<directoriodeinstalaciondelAPACHE>\htdocs” con el contenido:

TIP: En Windows las extensiones de los archivos no se suelen mostrar, así que en ocasiones crean el test.php pero en realidad esta como test.php.txt; para resolver esto, mediante opciones de carpetas, configuren su Windows para no oculte las extensiones conocidas
Verificamos que el Apache HTTP este arriba una vez reiniciado el PC, si no es así algo fue mal antes y deberían revisar el Event Viewer (Panel de Control)
Ahora a probar con:

http://localhost/test.php

Si obtiene una pantalla con información de la correcta instalación, todo va bien (caso contrario repetir los pasos anteriores, pero previamente des-instalando HTTP y PHP, incluida la eliminación del directorio físico). En esta información desplegada debe constar también la carga de los módulos mysql y mysqli que son necesarios para hacer trabajar al Joomla

6. Instalamos la versión 5.5 de MySQL (mysql-5.5.23-win32.msi) normalmente

7. Crear la base de datos “joomla” y el usuario “joomla” (con la clave que deseen), pueden ayudarse de una herramienta gráfica como MySQL GUI TOOLS (http://dev.mysql.com/get/Downloads/MySQLGUITools/mysql-gui-tools-5.0-r17-win32.msi/from/pick) que para mi es la favorita, o de una actual como MySQL WorkBench

8. Finalmente descomprimir el archivo del producto Joomla en el directorio “htdocs”, mencionado antes, en un nuevo directorio con el nombre “joomla” (u otro que deseen) y finalmente comienzan la instalación, que en algún momento les pedirá el nombre de la base de datos, el usuario y la clave; el resto es sencillo y no les dará problemas

9. (Opcional) si están migrando un sitio web con Joomla hay tres cosas por hacer: la primera copiar el directorio del sitio en el htdocs, la segunda crear la base de datos de mysql con el mismo nombre, clave y usuario de acuerdo a lo especificado en el archivo configuration.php de la carpeta del sito web siendo en resumen los siguientes

var $host = ‘localhost’; // This is normally set to localhost
var $user = ‘joomla’; // MySQL username
var $password = ‘miclave’; // MySQL password
var $db = ‘joomla’;

Y la tercera restaurar el respaldo de la base de datos del sitio web en la nueva base de datos creada

10. Finalmente probamos con http://localhost/joomla/index.php

Suerte!!!

General, General, Software , , , , , Leave a comment

Usando JPA e Hibernate en un ejemplo completo

Buenas tardes,

La idea de este post es ilustrar en un ejemplo completo, una aplicación este configurada mediante anotaciones JPA y la capa de persistencia Hibernate bien ensambladas; mencionando temas como el efecto CASCADE y FETCH en los mapeos (vía anotaciones). Finalmente se dejara el código fuente de este ejemplo para su análisis.

En breve descripción se usan tres tablas con nombres muy descriptivos: cliente, producto, orden y orden_detalle; la idea es que un cliente realiza una orden de algunos productos. Para esto empezamos a definir nuestras clases bean que tienen similares nombres: Cliente, Producto, Orden y OrdenDetalle respectivamente

Cliente.java

package com.corppm.technology.pruebas.entidades;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "cliente")
public class Cliente {
@Id
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "dna", nullable = false)
private String DNA;
@Column(name = "nombre_completo", nullable = false)
private String nombreCompleto;

public Long getId() {
return id;
}

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

public String getDNA() {
return DNA;
}

public void setDNA(String dNA) {
DNA = dNA;
}

public String getNombreCompleto() {
return nombreCompleto;
}

public void setNombreCompleto(String nombreCompleto) {
this.nombreCompleto = nombreCompleto;
}

}

Producto.java

package com.corppm.technology.pruebas.entidades;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "producto")
public class Producto {
@Id
@Column(name = "id")
private Long id;
@Column(name = "nombre", nullable = false)
private String nombre;
@Column(name = "sku", nullable = false)
private String SKU;
@Column(name = "precio", nullable = false)
private Double precio;

public Long getId() {
return id;
}

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

public String getNombre() {
return nombre;
}

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

public String getSKU() {
return SKU;
}

public void setSKU(String sKU) {
SKU = sKU;
}

public Double getPrecio() {
return precio;
}

public void setPrecio(Double precio) {
this.precio = precio;
}

}

Orden.java

package com.corppm.technology.pruebas.entidades;

import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "orden")
public class Orden {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "fecha", nullable = false)
private Date fecha;
@ManyToOne(fetch = FetchType.EAGER, optional = false)
private Cliente cliente;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = OrdenDetalle.class)
private List detalles;

public Long getId() {
return id;
}

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

public Date getFecha() {
return fecha;
}

public void setFecha(Date fecha) {
this.fecha = fecha;
}

public Cliente getCliente() {
return cliente;
}

public void setCliente(Cliente cliente) {
this.cliente = cliente;
}

public List getDetalles() {
return detalles;
}

public void setDetalles(List detalles) {
this.detalles = detalles;
}

}

OrdenDetalle.java

package com.corppm.technology.pruebas.entidades;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "orden_detalle")
public class OrdenDetalle {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne()
@JoinColumn(name="orden_id")
private Orden orden;
@ManyToOne(fetch = FetchType.EAGER, optional = false)
private Producto producto;
@Column(name = "cantidad", nullable = false)
private Integer cantidad;

public Long getId() {
return id;
}

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

public Orden getOrden() {
return orden;
}

public void setOrden(Orden orden) {
this.orden = orden;
}

public Producto getProducto() {
return producto;
}

public void setProducto(Producto producto) {
this.producto = producto;
}

public Integer getCantidad() {
return cantidad;
}

public void setCantidad(Integer cantidad) {
this.cantidad = cantidad;
}

}

En estos mapeos vamos a destacar algunas cuestiones:

  • GeneratedValue: Se aplicó solamente a las tablas de orden y orden_detalle, con la estrategia IDENTITY lo que quiere decir que la base de datos es la encargada de asignar un valor incremental (secuencial) en cada registro nuevo. Las otras dos tablas no tiene generación automática por tanto esperan que el id también sea pasado al construir el objeto.
  • ManyToOne: Usado en el mapeo de orden pago, dice que existe una referencia de un detalle a su orden padre, y a través de la anotación JoinColumn especificamos la columna de la tabla orden_detalle que tiene la referencia del registro padre en la tabla orden.
  • OneToMany: Por el otro lado en la tabla padre hacemos referencia a los detalle mediante esta anotación, especificando con que atributo de la clase hija (mappedBy) debe hacer la referencia en ninguna o todas las operaciones que se propagan desde el padre, por ejemplo al grabar, actualizar y/o borrar. Esta propagación se especifica mediante la propiedad CASCADE en nuestro caso configurado a ALL que instruye a la capa de persistencia de modo que toda aperacion sobre el padre afecte a los hijos (si borro una orden… se borraran sus detalles por ejemplo).

El sigiuente paso es configurar nuestras propiedades de persistencia, para eso y segun la especificacion se necesita definir un archivo llamado persistence.xml en el directorio META-INF situado a su vez en el directorio del compilacion del sistema (o de despoliegue en el caso de que ejecutemos en un contenedor). Vale anotar que para este efecto usamos MySQL como base de datos.
persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence 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"

 version="1.0">

 <persistence-unit name="testunit">
 <provider>org.hibernate.ejb.HibernatePersistence</provider>
 <properties>
 <property name="hibernate.show_sql" value="true"/>
 <property name="hibernate.format_sql" value="false"/>
 <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
 <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/hibernatecascade"/>
 <property name="hibernate.connection.username" value="pruebas"/>
 <property name="hibernate.connection.password" value="pruebas"/>
 <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<!-- <property name="hibernate.hbm2ddl.auto" value="create"/> -->
 </properties>
 </persistence-unit>

</persistence>

Sin mucho que comentar contiene las mismas propiedades que necesita una conexion comun, mas una consideracion importante acerca de provider que lo hemos definido como “org.hibernate.ejb.HibernatePersistence”, siendo esta característica el primer punto de ensamblaje entre Hibernate y JPA.
Por otro lado vemos que toda la configuración se envolvió en la etiqueta persistence-unit con nombre “testunit”; esto se debe a que se puede proveer varios punto de conexión que permitirían a una aplicación mucho mas compleja poder manipular los datos de varias bases de datos tranparentemente en la misma aplicación.

Finalmente creamos una clase con main, para ejecutar una simple operación de persistencia de este ejemplo:

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

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

import com.corppm.technology.pruebas.entidades.Cliente;
import com.corppm.technology.pruebas.entidades.Orden;
import com.corppm.technology.pruebas.entidades.OrdenDetalle;
import com.corppm.technology.pruebas.entidades.Producto;

public class Test01 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		EntityManagerFactory emf = Persistence
				.createEntityManagerFactory("testunit");
		EntityManager em = emf.createEntityManager();
		EntityTransaction tx = em.getTransaction();
		tx.begin();
		Query query = em.createQuery("SELECT o FROM Cliente o");
		if (query.getResultList().size() == 0) {
			poblarDatos(em);
		}
		Orden orden = new Orden();
		orden.setCliente(em.find(Cliente.class, 10L));
		orden.setFecha(new Date());
		List detalles = new ArrayList();
		OrdenDetalle ordenDetalle = new OrdenDetalle();
		ordenDetalle.setOrden(orden);
		ordenDetalle.setProducto(em.find(Producto.class, 100L));
		ordenDetalle.setCantidad(12);
		detalles.add(ordenDetalle);
		ordenDetalle = new OrdenDetalle();
		ordenDetalle.setOrden(orden);
		ordenDetalle.setProducto(em.find(Producto.class, 200L));
		ordenDetalle.setCantidad(99);
		detalles.add(ordenDetalle);
		orden.setDetalles(detalles);
		em.persist(orden);
		em.flush();
		em.remove(orden);
		tx.commit();
	}

	private static void poblarDatos(EntityManager em) {
		Cliente cliente = new Cliente();
		cliente.setId(10L);
		cliente.setDNA("1088888888201345");
		cliente.setNombreCompleto("Nombre Completo 1");
		em.persist(cliente);
		Producto producto = new Producto();
		producto.setId(100L);
		producto.setSKU("SKU001A");
		producto.setNombre("Producto A");
		producto.setPrecio(23.34);
		em.persist(producto);
		producto = new Producto();
		producto.setId(200L);
		producto.setSKU("SKU003B");
		producto.setNombre("Producto B");
		producto.setPrecio(11.09);
		em.persist(producto);
	}

}

Lo importante en este código es analizar la salida “output” en consola para que se percaten de que al borrar la orden borra también los detalles, con las instrucciones sql correspondientes” y se mantiene en consistencia a la propiedad CASCADE que explicamos anteriormente.

El link de descarga del codigo es:
hibernatecascade

Espero les sirva
Saludos

J2EE - JEE, Uncategorized , , , , Leave a comment

Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’

Hola,
Decidí desarrollar este post en vista de que este error varia de acuerdo a “en donde” el motor MySQL busca el archivo de extensión sock, es decir encontraremos casos con la misma descripción pero buscando el archivo en /etc/mysql/mysqld.sock por ejemplo. Lo cierto es que por varias razones de las instalaciones la ruta no esta del todo estandarizada, por tanto les recomiendo crear un link a su archivo físico sock de manera que el cliente de mysql lo ubique con su desenvolvimiento natural. Implica entonces el no modificar archivos como el my.cnf o php.ini o cualquier otro,
en mi caso el cliente lo busca en el directorio tmp con el nombre mysql.sock, así que lo primero es averiguar donde esta mi real archivo con una instrucción como:

find / -name "*.sock"

Seguramente hallarán uno con nombre mysql o mysqld en algún directorio relacionada a MySQL, en mi caso en /var/run/mysql/mysqld.sock. Nos queda entonces crear el link en /tmp para que mi cliente no tenga problemas al resolverlo:

ln -s /tmp/mysql.sock /var/run/mysql/mysqld.sock

Tan simple como eso volvemos a intentar la ejecución de nuestro cliente y caminaremos sin problemas.
Espero que esto les ayude con este inconveniente y no pasen tiempo como yo

BDD Topics, PHP Topics , , , Leave a comment

Interpretación commillas y comilla simple en Tomcat – escaped problem

Holas,

Estuve trabajando con una aplicación de hace algún tiempo y al cambiar de versión de tomcat para el deployed de la misma me tope con: ” quoted with ” which must be escaped when used within the value’ “, y la solución no es en realidad re-codificar todas las jsp con problemas… ya que podría suponer un esfuerzo demasiado alto en comparación al “porque?” estamos dando mantenimiento a la app. De todos modos les dejo un link, del cual básicamente aprendí a configurar los parámetros necesarios para decirle al Tomcat que los interprete sin tanta restricción

http://blog.neodoo.es/maznar/jboss/solucionar-el-error-is-quoted-with-%E2%80%9D-which-must-be-escaped-when-used-within-the-value-en-tomcat/

Espero que les sirva
Saludos

Other Topics , , , , Leave a comment

TIP: java.lang.UnsatisfiedLinkError: no ocijdbc10 in java.library.path en Linux

Holas,

Les dejo y me dejo un dato acerca de este problema que me saco un dolor de cabeza. Como ya saben mucha diferencia de OCI a THIN en Oracle, y bien, debíamos trabajar con OCI por un tema de balanceo. La aplicación no corrió satisfactoriamente dando el error mencionado.
Muchos lugares en Internet hablan de configurar LD_LIBRARY_PATH y es una alternativa pero en mi experiencia mejor hagan lo siguiente:

Descargen el “instantclient 10″ de Oracle
Descomprimanlo en cualquier directorio
Copien todos los lib* en su directorio del jre, algo como “/usr/lib/java/jdk1.5.0_22/jre/lib/i386″
Asegúrense de que están usando o el classes12.zip o el ojdbc14.jar en su proyecto que vinieron en el “instantclient 10″
Arranque su proyecto y listo

Aunque no lo he probado segura funcionara con “no ocijdbc9″ ya que es el mismo tema de las librerías.

Espero que les ayude
Saludos

BDD Topics, Java Topics , , , , , , Leave a comment

Manejar OnClick en una Celda de un Grid GWT

Holas,

Esta vez con un ejemplo de como utilizar el onclick sobre una celda de un gris que estemos construyendo con GWT, y me refiero al Grid de GWT como tal y no de SmartGWT u otros.

Bien, como saben para dibujar una celda de un Grid normalmente utilizamos la instrucción:

grid.setWidget(0, 0, new Label("Id"));

Que nos permite dibujar un Label por ejemplo, en una determinada posición (fila,columna), en general como podríamos pensar para darle un funcionalidad de onclick a este Label podríamos hacer algo como:

Label id = new Label(material.getId().toString());
id.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Window.alert("Hola");
}
});
grid.setWidget(0, 0, id);

Ok, para los que ya lo han hecho notaron que no funciona y al hacer click en el Label no sucede nada… como si no hubiéramos declarado el Handler. En realidad el Gris requiere de otra codificación pero aun así es totalmente viable configurar el evento. Veamos el siguiente código:


grid.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
HTMLTable.Cell cell = grid.getCellForEvent(event);
//Window.alert(cell.toString());
if (cell.getCellIndex() == 0 && cell.getRowIndex() == 0) {
//hacer algo
}
}
});

Como puede observar el evento maneja el click sobre el Grid y dentro de el mismo se puede determinar en que posición ocurrió el mismo: fila->cell.getRowIndex() y columna->cell.getCellIndex(). Si ustedes prueban el código observaran que al dar clic en la celda esperada este Handler definitivamente ejecutara lo especificado en el método.

No he encontrado una forma mas simple de manejar onclick sobre celdas pero esta forma va bien y funciona.

Espero que les sirva
Saludos

AJAX , , , Leave a comment

Superponer paneles o “bring to front” – gwt y smartgwt

Holas,

Al usar el ListGrid de smartgwt tuve problemas con ciertos popups y dialogbox al presentar mensajes, durante la operación de las pantallas; el tema fue que estos panales (divs) se presentaban tras el Listgrid u otros componentes dejando muy mal la presentación.

Revisando un poco me tope que tiene que ver con la propiedad z-index de CSS, que es el orden de como se sitúan los divs en una pantalla. La clave esta en setear esta propiedad con el valor mas alto posible.

Les dejo dos links de referencia

http://forums.smartclient.com/showthread.php?t=6208

http://www.sidar.org/recur/desdi/mcss/manual/ejemplos/zindex.html

Espero les sirva
Gracias

AJAX, Uncategorized , , , , Leave a comment

Como manejar la tecla tab en gwt

Holas,

Me encontre en la necesidad de dar una cierta accion y no la esperada al detectar un tab sobre un field del formulario “key press tab” pero este evento no es detectable al configurar un handle para el keypress del field; sino solo al manejar el keydown.

Les dejo un codigo de ejemplo y un link de mas informacion

doubleBoxUnidades.addKeyDownHandler(new KeyDownHandler() {

@Override
public void onKeyDown(KeyDownEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_TAB) {
//com.google.gwt.user.client.Window.alert("tab presionado.");
doubleBoxPrecioUnitario.setFocus(true);
}
}
});

http://albertattard.blogspot.com/2009/11/capturing-tab-key-in-gwt-textarea.html

Espero les sirva
Saludos

AJAX , , Leave a comment

@PersistenceUnit y @PersistenceContext + no transaction is in progress

Holas,

Voy a exponer unos conceptos básicos a la hora de elegir cual inyección usar en nuestros desarrollos, especialmente para aquellos que están dando los primeros pasos con JPA (de paso me dejo una base de conocimiento).

Lo primero que hay que entender es que JPA es un tecnología de la SUN que no necesita de una Servidor Web o Servidor de Aplicaciones para funcionar, de la cual existen algunas implementaciones entre ellas las mas notables como OpenJPA e Hibernate.

Por este motivo podríamos implementar nuestra capa de persistencia, con JPA, en una aplicación stand-alone, en un cliente-servidor o en ambientes web con servidores de web/aplicaciones

Dicho y entendiendo un conocimiento básico de JPA siempre veremos los archivos:
- persistence.xml (donde definimos nuestro/s persistence-unit)
- orm.xml o anotaciones (donde realizamos el mapeo de nuestras clases (conocidas tambien como DTO) a nuestras tablas de la bdd)
- EntityManager y EntityManagerFactory (con los que accesamos a las tablas para operaciones CRUD)

Bien vamos a suponer que tenemos configurados los dos primeros puntos, por tanto ya definimos las clases, las conexiones y los parámetros generales con nuestra bdd. En este punto estamos en un método de nuestros objetos de negocio que intenta escribir datos en la bdd, para la cual necesitamos la referencia de nuestro EntityManager.

Para esto podemos:

Usar @PersistenceUnit y obtener una instancia de EntityManagerFactory y de aqui crear un EntityManager con el cual podemos manejar las clases mapeadas a la tablas

@PersistenceUnit EntityManagerFactory entityManagerFactory;
EntityManager entityManager = entityManagerFactory.createEntityManager()
tx.begin(); //Iniciamos una transaccion para ejecutar las operaciones a la bdd
entityManager.find(..........
...
utx.commit(); //Comprometemos los cambios en la base

Todo va ok pero significa que cada ves que se ejecute este código, se crea una nueva instancia del EntityManager, y las operaciones que realizamos con esta las adherimos a la transaccion en cuestion. Esto no es malo, pero significa que ustedes deben controlar a nivel de su aplicacion cuando crean un transaccion, cuando la comprometen o la anulan y como alinear cada EntityManager creado… OHH y que pasa si no le dieron transaccion? entonces va a ver el famoso “no transaction is in progress” o que pasa si crearon una nueva en el flujo de ejecución de varios métodos de negocio? pues si la una falla la otra si termina y la base queda inconsistente o la una no ve el dato de la otra y graba valores inconsistentes etc. etc. etc.
Esto es inaceptable por ejemplo a escribirlo sobre atributos de servlets, pues recordemos que funcionan por hilos y sus EntityManagers van a ser el mismo dando una mezcla de commits y rollbacks inesperado.
Pero que hay si es una app del tipo stand-alone? pues bien…. me parece la opcion correcta, pero para este momento ya pueden decirdir ustedes :-)

Usar @PersistenceContext y obtener una instancia de “EntityManager” con el cual podemos manejar las clases mapeadas a la tablas

@PersistenceContext EntityManager entityManager;
// No hay begin del tx!!!!
entityManager.find(..........
...
// No commit tampoco!!!

Aja!!!, si nosotros no manejamos la persistencia significa que la delegamos a un container, como por ejemplo al Tomcat (servlet/server) un jboss (app/server) o spring (:-)). Ok el cambio es evidente no sabemos si sabremos cuando inicia o termina la transacción ni que entity manager nos entregaron, pero no nos preocupa porque lo hace un contenedor. Obviamente no justifica montar a o en un contenedor una app stand-alone, pero si es el caso ya podemos decidir que hacer.

en el caso de Spring hay un soporte total para JPA y estos comportamientos y no estamos hablando de usar un server, por lo que me parece (como en todo) la mejor opción en el caso supuesto.

Por ultimo les dejo dos lecturas complementarias que hablan de PersistenceUnit y PesistenceContext, y el link de como tratar el tema un poco mas “deep” con Spring.

http://javaevangelist.blogspot.com/2011/01/persistenceunit-vs-persistencecontext.html

http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/html/orm.html#orm-jpa-setup

Espero de verdad les sirva, gracias.

J2EE - JEE , , , , , Leave a comment