Foros del Web » Programación para mayores de 30 ;) » Java »

Problema JSF + EJB + JPA

Estas en el tema de Problema JSF + EJB + JPA en el foro de Java en Foros del Web. Intento resumir lo posible el problema: Voy directo a la parte de la aplicación que no entiendo su comportamiento. Esto implica 3 clases. La clase ...
  #1 (permalink)  
Antiguo 13/01/2014, 15:12
 
Fecha de Ingreso: noviembre-2013
Mensajes: 26
Antigüedad: 10 años, 5 meses
Puntos: 0
Problema JSF + EJB + JPA

Intento resumir lo posible el problema:

Voy directo a la parte de la aplicación que no entiendo su comportamiento. Esto implica 3 clases. La clase cliente se une con la clase cita (relación 1-n), y la clase cita se une con la clase factura (relación 1 a 1).

A la hora de mostrar el histórico de citas de un cliente lo muestra correctamente. En la tabla muestro información tanto de la cita (fecha) como de la factura (precio). El problema es que al facturar una cita, y tras esto ir al histórico, en esa tabla no recupera la información de la factura, cuando a mi parecer sí que debería de cogerla. En cambio al iniciar la aplicación de nuevo (se genera de nuevo el backing bean y managed bean), sí que lo muestra.

Pongo los métodos para que veáis:

hMB(backing bean):

Código:
    public String getCitas(Cliente c){
        this.citas = hLN.getCitas(c);
        return "hC";
    }
hLN(managed bean):

Código:
    public List<Cita> getCitas(Cliente c){  
        List<Cita> citas;
        citas = citaFacade.citasDeCliente(c);
        return citas;
    }
En citaFacade.citasDeCliente(c); hago una consulta JPA que devuelve el listado de las citas de ese cliente (funciona correctamente).

En el .xhtml en la tabla accedo de la siguiente forma:

<p:outputLabel value="#{cita.fechaIni}" >

<p:outputLabel value="#{cita.factura.precio}" />

El problema es que las cada vez que entro a getCitas lo hace correctamente, pero parece que la relación con factura no lo coge bien hasta que el backing bean no se genera de nuevo, la columna precio sale como vacía hasta entonces.

A ver si alguien me puede explicar este comportamiento.

Un saludo y gracias!
  #2 (permalink)  
Antiguo 13/01/2014, 15:31
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 2 meses
Puntos: 260
Sonrisa Respuesta: Problema JSF + EJB + JPA

Hola,

Cita:
Iniciado por malome88 Ver Mensaje
...
A ver si alguien me puede explicar este comportamiento.
Posiblemente el problema está en el caché de la implementación de JPA que estés usando, la transacción y el método de actualización de la Entidad.

Por ejemplo, si tienes una Entidad con una relación uno a muchos con otra Entidad, al hacer un merge se crea una nueva Entidad y se copian los valores que le pasaste de la Entidad sin los campos relacionados, (se pierde el campo relacionado). Al hacer la consulta de nuevo no actualiza la Entidad porque ya está en el caché.

Posiblemente, si CitasFacade es transaccional, intentan hacer un update(T) de esa Entidad en otra transacción, pero observa bien los límites de la transacción, tienes que hacerlo en otra transacción, puesto que si lo haces en la misma donde hiciste el merge ... simplemente no va a hacer el merge.

Saludos,
  #3 (permalink)  
Antiguo 14/01/2014, 03:42
 
Fecha de Ingreso: noviembre-2013
Mensajes: 26
Antigüedad: 10 años, 5 meses
Puntos: 0
Respuesta: Problema JSF + EJB + JPA

Hola, gracias por contestar.

La verdad es que no entiendo muy bien este tema, como hago lo que comentas de hacerlo en otra transacción?

La unidad de persistencia la tengo de la siguiente manera:

Código:
  <persistence-unit name="Proy-ejbPU" transaction-type="JTA">
    <jta-data-source>jdbc/Proy-database</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="eclipselink.temporal.mutable" value="true"/>
    </properties>
  </persistence-unit>
Saludos

Edito: Parece que funciona borrando la caché cada vez que llamo al método "citaFacade.citasDeCliente(c)".

He añadido lo siguiente: em.getEntityManagerFactory().getCache().evictAll() ;
y parece que funciona.

De esta forma cada vez que llame a este método borrará la caché y cargará lo que esté en la BD correctamente parece ser.

Última edición por malome88; 14/01/2014 a las 04:01
  #4 (permalink)  
Antiguo 14/01/2014, 12:52
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 2 meses
Puntos: 260
Sonrisa Respuesta: Problema JSF + EJB + JPA

Hola,

Cita:
Iniciado por malome88 Ver Mensaje
... como hago lo que comentas de hacerlo en otra transacción? ...
En algún lugar de tu aplicación se realiza una transacción, normalmente los EJB son transaccionales, pero no sabemos cuales son los límites de la transacción en tu aplicación, donde se inicia y donde termina.

Normalmente los Managed Beans no son transaccionales, aunque se pueden extender las transacciones hasta estos no es adecuado. Si esa fuera la arquitectura de tu aplicación con hacer un refresh antes del findAll debería funcionar.

Código Java:
Ver original
  1. public String getCitas(Cliente c){
  2.   hLN.updateCliente(c); // Método que haría el Upate.
  3.   this.citas = hLN.getCitas(c);
  4.   return "hC";
  5. }
Aunque no es seguro que funcione porque depende de la estructura y los límites de la transacción de tu aplicación.

Cita:
Iniciado por malome88 Ver Mensaje
... He añadido lo siguiente: em.getEntityManagerFactory().getCache().evictAll() ;
y parece que funciona. ...
Exactamente, borrando la cache es otro método, o desactivando la cache en el Persistence Unit. El único problema es que borra todos los caches; y otra vez, dependiendo de tu aplicación esto es algo que posiblemente no quieras hacer por motivos de desempeño.

Todo depende de tu aplicación y la forma que te funcione mejor.

Saludos,
  #5 (permalink)  
Antiguo 15/01/2014, 02:17
 
Fecha de Ingreso: noviembre-2013
Mensajes: 26
Antigüedad: 10 años, 5 meses
Puntos: 0
Respuesta: Problema JSF + EJB + JPA

Y en el update que es lo que haría? Nunca he tratado con este tipo de problema.

Saludos
  #6 (permalink)  
Antiguo 15/01/2014, 10:27
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 2 meses
Puntos: 260
Sonrisa Respuesta: Problema JSF + EJB + JPA

Hola,

Posiblemente, en su forma más simple podría ser así,

Managed Bean
Código Java:
Ver original
  1. public void update() {
  2.   myEnterpriseBean.merge(theCitaEntity);
  3.   myEnterpriseBean.refresh(theCitaEntityPrimaryKey);
  4. }
En el managed bean, después de hacer el merge, haces un refresh, aunque le puedes pasar solamente la llave primaria para hacer el refresh. Como en este caso los EJB son transaccionales, el update se va a hacer en una transacción y el refresh en otra.

EJB
Código Java:
Ver original
  1. public T merge(T t) {
  2.   return theEntityManager.merge(t);
  3. }
  4.  
  5. public void refresh(U u) {
  6.   theEntityManager.refresh(theEntityManager.getReference(TheClass, u));
  7. }
El método refresh del EntityManager necesita la entidad, para obtener la entidad sin cargarla de nuevo solamente usas getReference; este método necesita la Clase de la Entidad y la llave primaria.

De esa forma se actualiza la Entidad después de hacer el merge, y vuelve a traer los datos de la base de datos. Podrías probar a hacerlo después de hacer el merge de la Entidad que no se actualizaba o antes de hacer el findAll.

Saludos,

Etiquetas: clase, ejb, html, jpa, jsf, string
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 04:02.