Frage zu @PreUpdate und @PrePersist

Diskutiere Frage zu @PreUpdate und @PrePersist im Data Tier Forum; Hallo zusammen, durch Recherche zum Thema Auditierung bin ich auf die Annotation @PreUpdate und @PrePersist gestoßen (wir verwenden Java EE 5)....

  1. SilencerandLois
    SilencerandLois Mitglied
    Hallo zusammen,
    durch Recherche zum Thema Auditierung bin ich auf die Annotation @PreUpdate und @PrePersist gestoßen (wir verwenden Java EE 5).
    Was ich dadurch schonmal erreichen kann ist, dass ich automatisiert ein Erstellungsdatum / Änderungsdatum in der Entität setzen kann. Soweit so gut.
    Ich möchte aber nun noch zusätzlich den Benutzer in der Entität anpassen, sollte ein neuer Datensatz angelegt oder ein Update auf diesem durchgeführt werden.

    Leider habe ich auf Ebene der Entität keine Möglichkeit, den Sessionkontext abzurufen, da die Entitäten bei unserer gewählten Architektur wie folgt aussehen (wir verwenden als O/R-Mapper Eclipselink):

    Code (Java):

    @Entity
    public class XY implements {
    }
     

    Hat jemand von euch eine Idee, wie ich nun automatisiert bei einer Neuanalge / Änderung einer Entität neben den Zeitstempeln auch noch den Benutzer setzen kann?

    Besten Dank für eure Hilfe!
    Martin


    Den Sessionkontext hätte ich bei einer EJB-Entität wie folgt geholt:
    Code (Java):

    context.getCallerPrincipal().getName()
     
     
  2. Vielleicht hilft dir dieser Java-Kurs hier weiter --> (hier klicken)
  3. KSG9|sebastian
    KSG9|sebastian Aktives Mitglied
    Gar nicht..dafür sind PrePersist/.. nicht gedacht.

    Die Spec sagt
    Hibernate verbietet es sogar
    Dafür musst du wahrscheinlich Provider-spezifische Funktionen verwenden..bei Hibernate wären das Listener (Hiberante < 4). Später wurde dann ein entsprechendes SPI eingeführt..siehe Hibernate-Dok
     
  4. SilencerandLois
    SilencerandLois Mitglied
    Dachte ich mir schon fast :-(
    Gibt es eine ähnliche Funktionalität bei eclipselink?

    Wo würdet ihr ansonsten das Attribut setzen? In der Business-Logik?

    Danke!
     
  5. SilencerandLois
    SilencerandLois Mitglied
    -- Frage wurde wieder entfernt --
     
    Zuletzt bearbeitet: 20. Jan. 2014
  6. Spitfire777
    Spitfire777 Neues Mitglied
    Also wenn ich so etwas implementieren müsste, würde ich es tatsächlich in der Business-Logik machen und nicht im Datenmodell.

    Wenn du aber ganz dreist sein willst, könntest du das vielleicht mit einer Factory lösen, die dir den passenden Session-Context liefert. Die Factory könntest du dann in deiner PrePersist-Methode verwenden. Was ich dir aber nicht empfehle.

    Denn: Wenn dein Datenmodell entscheidet, welcher Benutzer nun genau zur Entity gehört, so kann es unter Umständen sein, dass du keine Chance haben wirst, dich drüber im Falle des Falles hinweg zu setzen. Zudem der nächste, der auf den Code schaut, sich beim Debuggen einen Wolf sucht.
     
    Zuletzt bearbeitet: 22. Jan. 2014
  7. SilencerandLois
    SilencerandLois Mitglied
    Danke Spitfire für deinen Kommentar.

    Das Factory-Pattern kenn ich schon. Aber wie würdest du das Umsetzen? Damit die Factory die Session kennt, müsste diese doch ein EJB sein, in welcher die Session über
    Code (Java):

    public void setSessionContext(final SessionContext sessionContext) {
    }
     
    automatisch durch JEE gesetzt wird. Wie kann ich aber dann von der Entität des Datenmodells auf die Factory-Klasse zugreifen? Oder verstehe ich deinen Lösungsansatz falsch?

    Sitz gerade auf dem Schlauf :oops:
    Wennsd kurz ein paar erklärende Codeschnippsel posten könntest, wäre ich dir sehr Dankbar!

    Viele Grüße,
    Martin

    P.S.: Dein Einwand mit der engen Kopplung beim Setzen des Benutzers im Datenmodell ist berechtigt. Stellt aber bei unseren fachlichen Bedürfnissen kein Problem dar. Diese könnten sich zwar natürlcih ändern, was ich in diesem Kontext jedoch stark bezweifle.
     
  8. KSG9|sebastian
    KSG9|sebastian Aktives Mitglied
    Öhm ich glaub kaum dass das funktionieren wird. Vermutlich kriegst du vom Persistenceprovider auf die Finger weil an der Stelle keine Interaktion mehr mit der Session machen darf .
    Was er meint ist den EntityManager in ein Singleton ( oder besser ThreadLocal) zu packen... dann kommst aus dem PrePersist dran.
     
  9. mackiex
    mackiex Neues Mitglied
    Ich weiß, es ist nicht die schönste Art von der Datenschicht auf die Session zuzugreifen.
    Muss man abwägen anhand der Architektur bzw. Modularisierung.

    Mit Spring Securtiy:

    private String getUsername()
    {
    try
    {
    final User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    return user.getUsername();
    }
    catch (final Exception e)
    {
    return "system";
    }
    }

    Man kann das aber mit Sicherheit noch entkoppeln. Session über Interface an Bean koppeln, etc ....
     
  10. SilencerandLois
    SilencerandLois Mitglied
    Ich wollte das Problem nun mit einer ThreadLocal-Variable lösen.
    Leider klappt es nicht so ganz.

    Was habe ich gemacht:
    1) In einem zentralen EJB-Container komme an meine Session. Hier lege ich den Benutzer nun in einer ThreadLocal-Variable ab. Durch Debuggen habe ich evaluiert, dass der Wert dort korrekt abgelegt wird. Die Methode wird auch nur ein einzigstes Mal beim Einloggen des Benutzers ausgeführt.
    Code (Java):

    class BusinessObject{
        public static final ThreadLocal<String> getAdmbName = new ThreadLocal();

        ....

        getAdmbName.set(context.getCallerPrincipal().getName());
     
    2) In meiner Entität greife ich nun in der mit @PreUpdate-Annotierten-Methode auf diese ThreadLocal-Variable zu. Ich befinde mich auch noch im selben Thread. Die Variable ist jedoch nicht gefüllt.
    Code (Java):

    @Entity
    class Entität {
       ...

       String getAdmbName = BusinessObject.getAdmbName.get();

       ...
    }
     
    Sollte es nicht so sein: wenn ich in einem einzelnen Thread unterwegs bin, dann kann ich bedenkenlos auf diese Variable zugreifen?


    Danke!
    Martin
     
    Zuletzt bearbeitet: 28. Jan. 2014
  11. KSG9|sebastian
    KSG9|sebastian Aktives Mitglied
    versuchs mal mit InheritableThreadLocal...
     
Die Seite wird geladen...

Frage zu @PreUpdate und @PrePersist - Ähnliche Themen

Berechnung des Paketportos - Problem/Frage
Berechnung des Paketportos - Problem/Frage im Forum Java Basics - Anfänger-Themen
Rekursion Verständnisfrage
Rekursion Verständnisfrage im Forum Java Basics - Anfänger-Themen
Frage zu Vergleichsoperatoren
Frage zu Vergleichsoperatoren im Forum Java Basics - Anfänger-Themen
Frage zu System.out.println
Frage zu System.out.println im Forum Java Basics - Anfänger-Themen
Frage zu ListView
Frage zu ListView im Forum AWT, Swing, JavaFX & SWT
Thema: Frage zu @PreUpdate und @PrePersist