4 Stimmen

Wann macht EntityManager commit?

Ich habe den folgenden Service...

@Stateless
@LocalBean
public class RandomService {

    @EJB RandomString stringTokenizer;

    @PersistenceContext
    EntityManager em;

    public String generate(Actions action)
    {
        Token token = new Token();
        token.setAction(action);
        token.setExpiry(new Date());
        token.setToken(stringTokenizer.randomize());

        em.persist(token);
        //em.flush();

        return String.format("%010d", token.getId()) + token.getToken();
    }
}

Wenn ich kein em.flush() setze, wird die Zeile token.getId() null zurückgeben (Verwendung der generierten Sequenz der Datenbank), obwohl ich weiß, dass wenn ich Token anstelle von String an den aufrufenden Service zurückgebe, die ID gesetzt ist. Es scheint also, dass EM flushes, wenn der Service ein Token-Objekt zurückgibt, aber nicht, wenn ich einen String setze. Indem ich flush setze, bekomme ich, was ich brauche. Ist das richtig so?

7voto

Tomasz Nurkiewicz Punkte 322861

Verwechseln Sie nicht das Ausführen mit dem Commit. Während flush() JPA-Anbieter generierten SQL physisch an die Datenbank sendet und in Ihrem Fall die generierte ID liest und im Bean einfügt. Beachten Sie, dass Sie immer das zurückgegebene Entity verwenden sollten, anstatt das ursprüngliche, das an persist() übergeben wurde:

token = em.persist(token);

Das Committing hingegen führt den Datenbank-Commit durch. Offensichtlich wird zuerst flush() ausgelöst, aber das wird Ihnen hier nicht helfen. Aber da Sie fragen - jede Methode in EJB ist standardmäßig transaktional. Das bedeutet, dass die Transaktion abgeschlossen wird, wenn Sie den ersten EJB im Stapel verlassen: wenn Sie eine EJB von einer anderen aufrufen, tritt die aufgerufene standardmäßig der Aufrufertransaktion bei (siehe: Verhalten der Transaktionsausbreitung).

Beachten Sie auch, dass die Regeln, wann flush() aufgerufen werden soll, etwas kompliziert sind, da jeder Anbieter versucht, dies so spät wie möglich und in Batches zu tun.

0 Stimmen

Ich scheine nicht in der Lage zu sein, token = em.persist(token); zu machen. Mit Netbeans 7.0.1 vermute ich, dass dies nur in den neuesten EJB-Versionen möglich ist.

1 Stimmen

Mein Fehler, es ist die merge(), die die neue Instanz zurückgibt, nicht persist(). Trotzdem musst du flush() explizit aufrufen.

0 Stimmen

Vielen Dank. Was denkst du über den obigen Code? Sollte ich die Formatierung am selben Ort oder auf einer höheren Ebene im Aufrufer durchführen?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X