2017-01-07 4 views
0

Ich versuche, Einträge zu einer Datenbank durch einen WebSocket-Aufruf in Java EE hinzufügen, immer noch das Lernen (ich verstehe auf jeden Fall noch nicht alle Konzepte). Ich erhalte die folgenden zwei Fehler je nachdem, wie ich meinen Code zwicken:Wie Entität in Java EE persistieren?

Fehler keine 1: java.lang.IllegalStateException: Exception Beschreibung: Es können keine EntityTransaction verwenden, während JTA verwenden.

Fehler kein 2: javax.persistence.TransactionRequiredException

Unnötig zu sagen, dass ich nichts in meine DB bekommen. Es gibt wahrscheinlich eine Menge Sachen in meinem Code und allgemeinem Design, die nicht optimal sind, irgendwelche Ratschläge oder Hinweise sind willkommen, aber die Frage ist, wo gehe ich von hier aus, um meinen Benutzer in die Datenbank zu bekommen?

Ich arbeite mit dem folgenden einfachen Setup, um etwas zu arbeiten, bevor Sie das volle Problem in Angriff nehmen.

Mein Entity:

@Entity 
@Table(name = "USER_TABLE") 
public class User implements Serializable { 

    @Id 
    private String name; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

Mein Datenzugriffsobjekt, am Ende das ist, wo die Magie DB Sachen für Benutzer passieren sollen:

public class UserDAO { 

    private EntityManager mEM; 

    public void save(User user) { 
     //mEM.getTransaction().begin(); // with comment = error no 2 | no comment = no 1 
     mEM.persist(user); // I was thinking that this was the magic I needed. 
     //mEM.getTransaction().commit(); // with comment = error no 2 | no comment = no 1 
    } 

    public void setEM(EntityManager em) { 
     mEM = em; 
    } 
} 

Ich habe auch eine DatabaseIO, mein Denken ist Wenn ich mehr als nur Benutzereinheit habe, würde ich gerne alle IO-Daten der Datenbank in einer Klasse sammeln:

public class DatabaseIO { 

    private EntityManager mEM; 

    public DatabaseIO(EntityManager em) { 
     System.out.println("DatabaseIO(" + em + ")"); 
     mEM = em; 
    } 

    public void createUser(String name) { 
     System.out.println("createUser(" + name + ")"); 
     User user = new User(); 
     user.setName(name); 

     UserDAO userDAO = new UserDAO(); 
     userDAO.setEM(mEM); 
     userDAO.save(user); 
    } 
} 

Dann habe ich einige Klassen, die die Datenbank IO verwenden und die Anforderungen behandeln, die in die Anwendung kommen. Grundsätzlich die Geschäftslogik. Ich habe dies nicht als Bean bezeichnet, da diese mit jedem Benutzer erstellt werden, der sich mit der Anwendung verbindet. Und sobald sie verbunden sind, muss Benutzer1 möglicherweise auf das SomeClass-Objekt von Benutzer2 zugreifen, war nicht sicher, wie dies zu erreichen wäre, ohne die Objekte selbst zu erzeugen, anstatt den Container.

public class SomeClass { 

    private DatabaseIO mDbIO; 

    public SomeClass(EntityManager em) { 
     mDbIO = new DatabaseIO(em); 
    } 

    public void newUser(String name) { 
     mDbIO.createUser(name); 
    } 
} 

Ich habe eine EJB, die mit der Anwendung startet und hält einige Status für alle von der Anwendung, nicht sicher, ob dies ist die beste (höchstwahrscheinlich gibt es bessere Möglichkeiten, war mein Ziel nicht Sache gestellt ich oft brauchen in der Datenbank, bis ich mit ihm) Art und Weise fertig, aber es ist das, was ich mit so weit habe kommen:

@Startup 
@Singleton 
@Named("some_manager") 
public class SomeApplicationManager { 

    @PersistenceContext(unitName="AddUsersPU") 
    private EntityManager mEM; 

    public EntityManager getEM() { 
     return mEM; 
    } 
} 

Und schließlich meinen WebSocket Endpunkt:

@ServerEndpoint("/WebSocket") 
public class WebEndpoint { 

    @Inject 
    SomeApplicationManager mAppManager; 

    @OnOpen 
    public void onOpen(Session aSession, EndpointConfig aConfig) { 
     aSession.addMessageHandler(new MessageHandler.Whole<String>() { 
      @Override 
      public void onMessage(String aUserName) { 
       System.out.println("new user: " + aUserName); 
       SomeClass aClassObj = new SomeClass(mAppManager.getEM()); 
       aClassObj.newUser(aUserName); 
      } 
     }); 
    } 

} 

ich das getestet wurde eine einfache JavaScript und ich bekomme die Eingabe erwarte ich bis zu den Zeilen in UserDAO, wo ich kommentiert habe, dass ich einen Fehler erhalte.

EDIT: Von dem, was ich verstehe, von den Antworten unten und einige mehr googeln, ist der Grund, warum mEM.persist (Benutzer) nicht funktioniert, weil es nicht durch den Container verwaltet wird. Ich versuchte, dies zu beheben, indem ich UserDAO als @Stateless annotierte und es wie vorgeschlagen durch DatabaseIO in @EJB injizierte. Dies gab mir jedoch eine NullPointerException. Ich beschriftete dann auch DatabaseIO und SomeClass als @Stateless und anstatt SomeClass in WebEndpoint (und DatabaseIO in SomeClass) explizit zu erstellen, injizierte ich es mit @EJB. An diesem Punkt habe ich tatsächlich eine Entität in die Datenbank bekommen, aber ich bin mir nicht sicher, ob ich alles verstehe.

+0

Ich habe etwas ähnliches gemacht und es hat für mich funktioniert. Bitte werfen Sie einen Blick –

Antwort

0

Machen Sie Ihre UserDAO zu einer Session Bean und verwenden Sie die Annotation @PersistenceContext, um den Persistenzkontext in diesen einzufügen. Der Grund für Ihren Fehler 1 ist, dass Sie JTA verwenden und Sie die Transaktion nicht verwalten dürfen. Sie erhalten eine Transaktion, wenn Sie eine EJB-Methode eingeben (es sei denn, Sie geben explizit eine Transaktion an). Und Sie brauchen kein Singleton, um Persistenzkontext zu liefern, der Container wird damit umgehen.

@Stateless 
public class UserDAO { 

    @PersistenceContext(unitName="AddUsersPU") 
    private EntityManager mEM; 

Und Injizieren Sie die EJB mit @EJB Anmerkung

@EJB 
private UserDAO userDao; 

Ist alles was Sie benötigen, und nicht die EM in diesem Satz, dh., Entfernen Sie die

public void setEM(EntityManager em)` 

Methode

+0

Scheint einfach genug, aber ich bekomme eine NullPointerException, wenn ich dies versuche, meine Vermutung ist, dass weil ich UserDAO selbst (?) Erstellen, scheint der Container nicht den EntityManager dann injizieren. (Es ist in meinem SomeApplicationManager oben). Gibt es eine Möglichkeit für mich, einen Verweis auf einen @Stateless UserDAO zu erhalten, ohne ihn selbst zu erstellen? –

+0

Ja, verwenden Sie @EJB. Siehe die Änderung –