JPA - aktualisierung von gleichen Entities

Denny1989

Aktives Mitglied
Mal ein Frage. ich entwickle eine jsf anwendung die mit JPA und entities arbeitet. Ich speichere manchmal ein Entity in ein @SessionScoped bean. Wenn ich selbiges Entity in einem anderen browser zb. auswähle und ändere bekomme ich das ja im 1. browser nicht mit z.b. wenn ich die seite neu lade.

Gibt es denn eine Möglichkeit oder einen Ansatzpunkt das so hinzukriegen dass die Daten synchron sind?

Weiteres beispiel:
Ein Entity hat einen status und wird in einem Sessionbean gespeichert. ich ändere bei selbigen Entity in der DB den status. Danach ändere ich im programm andere werte an dem Entity und rufe em.merge() auf. Daraufhin steht in der DB wieder der alte wert von "status" weil JPA es nicht mitbekommen hat dass sich zwischendurch was an dem Objekt geändert hat.

Ist das normal? Das problem tritt ja sozusagen auf jede Multi-user anwendung zu. (also jede Website!?)

Ich nutze glassfish v3 mit eclipselink 2.1 so weit ich weiß. keine zusätzlichen Bibliotheken.
 
N

nillehammer

Gast
Ich speichere manchmal ein Entity in ein @SessionScoped bean. Wenn ich selbiges Entity in einem anderen browser zb. auswähle und ändere bekomme ich das ja im 1. browser nicht mit z.b. wenn ich die seite neu lade.

Gibt es denn eine Möglichkeit oder einen Ansatzpunkt das so hinzukriegen dass die Daten synchron sind?
Entities in der Session (Web) zu halten, ist keine gute Idee. Nutze das Open-Session-In-View-Pattern (dies mal Hibernate Session gilt auch äquivalent für den EntityManager) und hole Dir die Entity für jeden Request neu.

Weiteres beispiel:
Ein Entity hat einen status und wird in einem Sessionbean gespeichert. ich ändere bei selbigen Entity in der DB den status. Danach ändere ich im programm andere werte an dem Entity und rufe em.merge() auf. Daraufhin steht in der DB wieder der alte wert von "status" weil JPA es nicht mitbekommen hat dass sich zwischendurch was an dem Objekt geändert hat.

Ist das normal? Das problem tritt ja sozusagen auf jede Multi-user anwendung zu. (also jede Website!?)
Nutze Optimistic Locking mit einem Version Feld. Dann bekommt JPA mit, dass woanders eine Änderung gemacht wurde.
 

Denny1989

Aktives Mitglied
Es ist also so nativ mit em.merge() niemals möglich ein Entity zu verändern und zu speichern wenn sich in der DB was geändert hat? also dass man das irgendwie mitbekommt? da muss man dann ein Version feld in jede tabelle schmeißen?

Kannst du mir mal in 2 sätzen die idee Open-Session-in-View nennen ? Ist bisschen umfangreich, vor allem da es nur texte bezüglich Hibernate gibt!?
 

Denny1989

Aktives Mitglied
Mal noch ne generelle Frage:
Wenn ich ein Entity ändern möchte hole ich mir das meist in einem seitenaufruf aus der DB und speichere es in der Sessionbean. Im nächsten request werden dessen properties geändert durch die bindung an Formularfelder, danach rufe ich mehr oder weniger em.merge() auf. das ist dann nicht die richtige vorgehensweise oder? Wäre es besser die Formularfelder an einzelne Variablen zu binden um danach im Request, das gespeicherte Entity an hand des Primärschlüssels neu aus der DB zu holen , zu ändern und dann em.merge() aufzurufen?
 
M

maki

Gast
Es ist also so nativ mit em.merge() niemals möglich ein Entity zu verändern und zu speichern wenn sich in der DB was geändert hat?
Du meinst wohl "naiv" anstatt "nativ".
Wenn die Datenkonsistenz nicht so wichtig ist und dem User egal ist ob auch das in der DB steht was er eingegeben hat, kannst du natürlich mergen anstatt zu locken...

nillehammer hat dir schon den entscheidenden Hinweis gegeben.: Optimistic Locking

Ansonsten solltest du dich vielleicht mal generell in Locking einlesen (Optimitis vs. Pessemistic, dann die Offline und Online Varianten).

Bim OpenSessioninView Pattern geht es darum, dass immer eine Session vorhanden ist wenn man die Entity in der View anfässt, zwischen den Requests wird sie aber geschlossen.
 

Denny1989

Aktives Mitglied
Baue i also ein version feld ein und nutze optimistic locking (stellt man das in der persistence.xml ein?) dann steht nach einem merge im entity der neue wert aus der db drin und es überschreibt die änderungen nicht?

Habe nämlich das problem wenn ein user gesperrt wird (status =0) und in der session der user noch mit status 1 steht dass nach em.merge der status natürlich wieder auf 1 steht und das bei ner profiländerung eines nutzers passiert obwohl der nutzer das eig garnicht ändern können soll.
 
M

maki

Gast
Baue i also ein version feld ein und nutze optimistic locking (stellt man das in der persistence.xml ein?) dann steht nach einem merge im entity der neue wert aus der db drin und es überschreibt die änderungen nicht?
Dann fliegt eine OptimisticLockingException.
Wenn du keine Exception willst, musst du pesemistisch Locken.
Wo & wie du das einstellst steht in der Doku, und noch viel mehr ;)

Habe nämlich das problem wenn ein user gesperrt wird (status =0) und in der session der user noch mit status 1 steht dass nach em.merge der status natürlich wieder auf 1 steht und das bei ner profiländerung eines nutzers passiert obwohl der nutzer das eig garnicht ändern können soll.
Dateninkonsistenz, da hab ich ja schon beschrieben:
Wenn die Datenkonsistenz nicht so wichtig ist und dem User egal ist ob auch das in der DB steht was er eingegeben hat, kannst du natürlich mergen anstatt zu locken...
spezifischer: Du beschreibst ein sog. "Lost Update"
 

Denny1989

Aktives Mitglied
ja stimmt lost update heißt das hab ich auch schon mal gelernt -.-

wäre das hier eine einigermaßen taugliche lösung für mein problem mit den stati? Denn irgendwie muss ich ja gewährleisten dass admin und user gleichzeitig arbeiten könne oder!?
Wäre es besser die Formularfelder an einzelne Variablen zu binden um danach im Request, das gespeicherte Entity an hand des Primärschlüssels neu aus der DB zu holen , zu ändern und dann em.merge() aufzurufen?
 

Denny1989

Aktives Mitglied
oha. Stati ist blödsinn, das ist mir neu. danke

nochmal darauf eingehakt:
Wenn ich locking verwende und jemand sein profil bearbeitet und während dem laden aus der DB und dem speichern in die db in der DB eine änderung vorgenommen wurde, dann schlägt ja der komplette update vorgang fehl oder? d.h. wenn jemand ein längeren text in sein profil tippt die möglichkeit besteht dass dieser ja durch diese LockingException verhindert wird das überhaupt die änderung übernommen wird.
 
M

maki

Gast
Hi,

es gibt da einen Unterschied zwischen PessemisticLocking und OptimisticLocking, wie bereits angedeutet.

Optmistic schlägt beim Update fehl, Pessemistic lässt nur einen auf einmal editieren.
 

Denny1989

Aktives Mitglied
ich weiß ich nerve dich aber ist das nicht dann völlig ungeeignet für eine Webseite? Szenario:

Person a ruft ihr Profil auf und bekommt es angezeigt, braucht 5 minuten um die informationen im formular einzutragen.(status=1)

Währenddessen ruft Admin das profil von Person a auf und setzt (status=0)

Person a drückt danach auf submit und möchte seine änderungen in die db schreiben, hat aber keinerlei einfluss auf status und weiß auch garnicht das diese variabe existiert. Bei optimistic locking würde jetzt das speichern fehlschlagen was ja nicht gewollt ist!? bei em.merge() steht status=1 wieder in der db was auch nicht gewollt ist. Setze ich im Entity status auf @Column(updatable=false) kann auch der admin diese Spalte nicht ändern.

zu pessimistic locking: wann wir d denn da gelockt? beim aufrufen der profildaten ändern seite ? dann kann der admin währenddessen ja auch nicht auf das profil zugreifen bzw. nix ändern. Müsste es nicht irgendwie möglich sein dass der admin den status ändert /ändern kann und der user nicht!?
 
M

maki

Gast
Du nervst nicht, ich muss ja nicht antworten.

Dir hilft ein Forum bei so komplexen Fragen aber nicht wirklich, du musst dich schon einlesen/weiterbilden, deswegen die Hinweise/Suchbegriffe von mir.

PessemisticLocking hat eingie Nachteile, ist manchmal aber zwingend erforderlich, willst ja keinen user 30 Minuten Daten einhacken lassen um dann seine Daten wegen einer OptmisticLockingException zu verwerfen.
Für die meisten Anwendungsfälle ist optimistisches Locking ausreichend.

Was gelockt wird musst du entscheiden ;)

Die Theorie ist ja schon komplex genug, richtig schwierig wird es in der Realität.

Dein beispiel scheint hofefntlich nicht realistisch zu sein, wie oft ändern User ihre Profildaten während sie vom Admin gesperrt werden?
Wie wichtig ist dann das ihre Änderungen nciht übernommen wurden?
 

Denny1989

Aktives Mitglied
doch es ist realistisch. das sperren bedeutet hier nicht dass der user nix mehr tun kann sondern nur dass er für gäste nicht mehr nach aussen sichtbar ist. Es soll dem nutzer also trotzdem erlaubt sein Änderungen durchzuführen. und da isses natürlich doof wenn die in diesem zugegebenermaßen unwahrscheinlichen, aber dennoch möglichen fall verloren gehen.
 

Ähnliche Java Themen


Oben