2016-07-12 25 views
0

Aus irgendeinem Grund wird der EntityManager nicht in einen separaten Thread injiziert, den ich im Hintergrund weiterlaufen lassen möchte. Andere Klassen können ohne Probleme auf den Entity Manager zugreifen, aber diese laufen nicht in einem separaten Thread.PersistenceContext im Multithreading

Was mache ich hier falsch?

@Stateful 
public class DatabaseManager extends Thread{ 
    @PersistenceContext(unitName="imas-unit") 
    private EntityManager em; 


    private int timeBetweenRefresh; 

    public void run(){ 
     loadProperties(); 
     retrieveDBContent(); 
     long timerTicks = System.currentTimeMillis(); 
     while(running){ 
      if(System.currentTimeMillis() > timerTicks + timeBetweenRefresh){ 
       timerTicks = System.currentTimeMillis(); 
       deleteAllRecords(); 
       retrieveDBContent(); 
      } 
      Thread.sleep(1000); 
     } 
    } 

    private void deleteAllRecords(){ 
     //Deletes all the records 
    } 

    private void loadProperties(){ 
     //Loads properties for methods 
    } 

    private void retrieveDBContent(){ 
     List<Cel> celList = methodThatGetsCells(); 
     System.out.println("Saving to database"); 
     for(Cel cell : celList){ 
      try{ 
       em.persist(cell); //Null pointer here 
       em.flush(); 
      } 
       catch(Exception e){ 
        System.out.println(e.getMessage()); 
        e.printStackTrace(); 
       } 
      } 
     } catch (InterruptedException e1) { 
      // TODO Auto-generated catch block 
      System.out.println("Retrieval failed. Please check error log for further information."); 
      e1.printStackTrace(); 
     } 
    } 

} 

Ich kann bei Bedarf weitere Informationen buchen.

Antwort

1

Ich denke, dass Sie darüber ein bisschen falsch denken. Der Container wird deine Stateless-Bohne herausnehmen, wenn sie denkt, dass sie erledigt ist - sie weiß nicht, dass du einen Thread abgesponnen hast.

Ich würde mit der @ Schedule Annotation und vielleicht @Singleton aussehen. Es sieht so aus, als würden Sie regelmäßig eine DB-Wartung durchführen und wahrscheinlich nicht mehr als eine Bean, die das tut. So etwas wie:

@Singleton 
public class DatabaseManager { 
    @PersistenceContext(unitName="imas-unit") 
    private EntityManager em; 

    ... 

    @Schedule(minute = "*", persistent = false) 
    private void yourMaintenanceMethod() { 
    ... 

Die Methode "yourMaintenanceMethod" würde in diesem Beispiel erhält jede Minute laufen. Sie können ein Sekundenfeld eingeben, um zum Beispiel alle 15 Sekunden oder was auch immer Sie benötigen zu laufen.

Ich habe dieses Muster in der Vergangenheit erfolgreich für ähnliche Arten von Dingen verwendet - es lässt im Grunde den Container das Threading tun und vereinfacht schließlich Ihren Code ein wenig.

+0

Wusste darüber nicht. Nun, das hat die Sache 10 mal einfacher gemacht. – Strike08