2012-04-30 8 views
7

Después de construir el bean, quiero recuperar los datos de la base de datos, usando EntityManager. No es posible en el constructor, porque EntityManager se inyecta después de llamar al constructor. Así que traté de hacerlo en un método anotado con @PostConstruct. De acuerdo con la API, se llama a los métodos PostConstruct después de que se hayan realizado todas las inyecciones. La ejecución de la consulta funciona, pero siempre devuelve una lista vacía. Si utilizo la misma consulta en otro método, devuelve el resultado correcto. ¿Alguien sabe por qué no funciona en el método PostConstruct?EJB: Usando EntityManager en el método PostConstruct

@Stateful(mappedName = "price") 
@Singleton 
@Startup 
public class PriceManagementBean implements PriceManagement { 

    @PersistenceContext 
    private EntityManager em; 

    private List<PriceStep> priceSteps = Collections.synchronizedList(new ArrayList<PriceStep>()); 


    public PriceManagementBean(){ 


    } 


    @PostConstruct 
    public void init(){ 
     javax.persistence.Query query = em.createQuery("SELECT ps FROM PriceStep ps"); 
     List<PriceStep> res = query.getResultList(); 
      ..... 
     } 
} 
+0

Ver http://stackoverflow.com/questions/2399769/is-it-okay-to-pass-injected-entitymanagers -to-ejb-beans-helper-classes-and-use – mglauche

+0

¿Cómo y dónde se agregan los PriceSteps al db? – Puce

+0

Su bean está anotado tanto 'Stateful' como' Singleton', lo que no está permitido. Si su contenedor EJB no es compatible con EJB 3.1, ¿tal vez el bean es realmente con estado, y PostConstruct se está ejecutando con un contexto de transacción indefinido, y su servidor de aplicaciones no es compatible con eso? ¿Qué servidor de aplicaciones estás usando? –

Respuesta

9

¿Alguien sabe, por lo que no funciona en el método PostConstruct?

Razón 1 No se puede crear un bean que es, al mismo tiempo @Stateful y @Singleton (Bien se puede pero no tendrá sentido desde Singleton también son estado), que es una de las razones estás teniendo problemas No hay excepciones, pero hay un conflicto allí, debes arreglarlo primero.

Sólo recuerde:

  • frijol Un Singleton es un bean que mantains su estado. Solo hay una instancia de Singleton en una aplicación y se comparte entre todos los usuarios de la aplicación. Además, dado que es un bean compartido (tal vez mejor decir concurrente), es necesario implementar algún tipo de mecanismo de bloqueo utilizando la anotación @Lock.

  • Un bean Stateful es un bean que mantiene cada estado después de una transacción. Cuando se trabaja con
    beans con estado de cada usuario obtiene una copia del grano que durará todo el tiempo que la sesión - dura o hasta que un método anotado con @Remove se llama

Razón 2 Incluso si funciona, no podrá acceder a los resultados, porque los está almacenando en un objeto llamado res al que solo se puede acceder desde el método init(). Supongo que le gustaría asignar ese valor devuelto a la variable priceSteps.

De todos modos hay muchas cosas mal en su código, por no decir todo. No sé cuáles son sus requisitos de sistema, pero aquí le daré una solución simple que le permitirá acceder a la base de datos:

Supongo que está tratando de devolver los datos en el ciclo de vida de alguna manera el bean porque desea evitar enviar consultas una y otra vez si el bean es @Stateful. Lo que pasa es que no tiene que hacer eso, aún puede hacer que su bean @Stateless y evite estresar su base de datos con muchas consultas. Lo que necesita hacer es crear un @NamedQuery.

Así Anote en su entidad PriceStep con @NamedQuery y no entran en la cadena de consulta que escribió.En este enlace encontrará información sobre cómo utilizar @NamedQueries: http://docs.oracle.com/cd/B31017_01/web.1013/b28221/ent30qry001.htm

La siguiente cosa que sugeriría que es para anotar su clase PriceManagementBean como * @Stateless *. No se preocupe si en cada solicitud se crea un nuevo entityManager, que no acentúa la base de datos, ya que interactúa con el modelo de dominio. No necesita @PostConstruct, simplemente llame a su @NamedQuery cada vez que lo necesite y eso es todo. El servidor de aplicaciones lo almacenará en la memoria caché y se lo devolverá a cada usuario que lo requiera sin interactuar con la base de datos todo el tiempo.

Aquí un codesnipet:

@Entity 
@NamedQuery(
    name="allPriceSteps", 
    queryString="SELECT ps FROM PriceStep ps" 
) 
public class PriceStep implements Serializable { 
... 
} 

Ahora el grano:

@Stateless 
public class PriceManagementBean implements PriceManagement { 

    @PersistenceContext 
    private EntityManager em; 

    public List<PriceStep> getAllPriceSteps() { 
     Query query = em.createNamedQuery("allPriceSteps"); 
     return query.getResultList(); 
    } 
} 

Espero que esto sea útil. Si proporciona más información sobre los requisitos de su sistema, podemos aconsejarle sobre las mejores prácticas.

+0

Estoy experimentando exactamente el mismo problema, pero su respuesta no cubre mi caso. Tenemos un caché como un bean '@ Singleton', que se completa en el método' @ PostConstruct'. Esto ha funcionado bien, pero estoy empezando a experimentar un problema durante la reescritura de las pruebas. Creo que la razón es que anteriormente ejecutamos las pruebas en una base de datos ya poblada, pero ahora intentamos usar HSQLDB en memoria. Dado que la prueba se ejecuta en una transacción, sospecho que el código en '@ PostConstruct' no es parte de la misma transacción, lo que da como resultado una lista vacía. ¿Tienes alguna idea sobre eso? – Magnilex

+0

Lo mismo aquí, y no estoy usando statefuls ni nada de eso. – momomo

-2

Sobre la base de sus necesidades intenta lo siguiente

  • Retire @Stateful [No se puede utilizar tanto en un momento]

  • @Startup inicializará frijol Singleton durante INIT APLICACIÓN [Por favor, tenga en cuenta que la aplicación NO se ha inicializado por completo]. Esto podría causar algún problema al cargar EntityManager y supongo que el puente de EntityManager no se ha inicializado por completo. Trate de llamar a la inicialización después de inicio de la aplicación completa [es decir,] Retire @Startup

Cuestiones relacionadas