Hibernate update-Problem

Status
Nicht offen für weitere Antworten.

k4lle

Mitglied
Ich hoffe mein Topic ist an dieser Stelle richtig.
Ich habe folgendes Problem: Ich schildere kurz die Theorie. Vielleicht verstehe ich ja etwas falsch und kann dann selber weiterbasteln.

Das Speichern eines Objekts: Objektzustand:
- Session & Transaction wird gestartet new -> transient
- Das Objekt wird gespeichert save -> persistent
- Transaction und Session wird beendet close -> detached

Das Laden eines Objekts:
- Session & Transaction wird gestartet
- das ausgewählte Objekt aus h:dataTable load -> persistent
mit ID=?? wird geladen
- Transaction und Session wird beendet close -> detached


Jetzt kommt mein Problem:
Ich will das gerade ausgewählte Objekt aus der Liste updaten. Hierzu wähle ich ein Objekt aus und lasse es mir in einem Formular anzeigen. Jetzt will ich den Button ändern betätigen können und das Objekt soll geupdatet werden.
Hierzu will ich Operation update() benutzen.

Bisher klappt nur das Updaten eines Objekts, dass ich gespeichert habe und dann sofort wieder update. Sobald ich mich von der Anwendung abmelde und ein beliebiges Objekt aus der Liste auswähle, kann ich dieses nicht updaten.
Ich bin der Meinung, dass es mit dem Hibernate-Objektzustand zu tun hat. Mir ist klar, dass einiges dazu in der Hibernate-Doku steht, aber wenn ich mir hätte dadurch weiterhelfen können würde ich hier nicht nachfragen :)

Es wäre sehr schön, wenn mir jemand die Theorie zum updaten eines Objekts im detached-Zustand sagen könnte.
Außerdem wäre es schön, wenn jemand sagen könnte ob ich mit meinen Objektzuständen die ich oben genannt habe recht habe. Falls ich Code posten soll, kann ich das gerne machen. Es geht mir aber jetzt erstmal um die Theorie.

Vielen Dank...
 
S

SlaterB

Gast
> kann ich dieses nicht updaten.

wie zeigt sich das?
hat das zu updatende Objekt eine Id gesetzt?

kannst du zum Zeitpunkt des Fehlers auf normalem Wege das Objekt zu dieser Id laden?
ist es vielleicht schon geladen und in der Session vorhanden?
dann könnte ein Update mit einem anderen Objekt Ärger machen,
aber so genau weiß ich das grad auch nicht
 

k4lle

Mitglied
um das ganze besser zu beschreiben folgendes:
es geht nur um das updaten:

habe in meiner DB ca. 20 Objekte.

1) starte meine anwendung
2) wähle aus einer liste die durch eine tabelle dartgestellt wird ein objekt aus
3) dieses objekt lade ich mit hilfe der ID in ein formular (die ID wurde durch Hibernate vergeben)
4) jetzt möchte ich dieses objekt updaten (also einfach durch die Operation update())
bis da klappt alles wie es soll

5) ????? welchen Objektzustand hat mein Objekt (laut meinem verständnis hat es den zustand detached)
wie speichere ich genau ein objekt des zustand detached. muss es nicht zuerst zurück in den zustand persistent um
gespeichert zu werden?


wäre schön, wenn du mir erklären könntest, wie der punkt 5) theoretisch aussehen muss?????

PS: Gibt es eine Operation, mit der ich mir den Hibernate-Objektzustand ausgeben lassen kann???? Das würde mir glaube ich absolut weiterhelfen. Dann würde ich mehr verstehen :)
 
S

SlaterB

Gast
ne, aber hab das Buch ;)

das fand ich allerdings recht oberflächlich zu beiden Themen,
was nicht bedeutet, dass ich mehr weiß, vergesse eh das meiste wieder ;)
 

happy_robot

Bekanntes Mitglied
du musst eigentlich nichts anderes machen als "saveOrUpdate" aufrufen nach einer änderung.

den zustand detached hat es erst wenn du ein evict auf dem objekt aufrufst.
damit werden alle referenzen zum ursprünglichen db-objekt "vergessen".
ansonsten bleibt das objekt immer "attached".
detachte objekte können grundsätzlich kein update erhalten weil der bezug zur datenbank ja gänzlich fehlt.
 

k4lle

Mitglied
also wenn ich mich an das hibernate-zustandsmodell halte, dann gelangen laut meinem verständnis die persistenten objekte nachdem die session geschlossen wird in den zustand detached.
jetzt lade ich das (detached) objekt und möchte es updaten.

wenn ich saveorUpdate benutze geschieht folgendes:

ich lade das objekt aus der DB. Zb. ein Objekt mit der ID 34. (ID wird automatisch beim Speichern zugewiesen).
- das sieht wie folgt aus:

Code:
public String aendernMaschinendaten(){
		System.out.println("ID= " + aMaschinendaten);
		//Session holen und Aufruf der Methode HibernateSessionVerwaltung.getSession()
		Session session = HibernateSessionVerwaltung.getSession();
		//aktuell ausgewähltes Objekt wird geladen
		Maschinendaten dieMaschinendaten = (Maschinendaten) session.load(Maschinendaten.class, aMaschinendaten);
		//Bean Properties erhalten aktuell ausgewählte Werte
		maschinendaten.setBetriebsmittel(dieMaschinendaten.getBetriebsmittel());
...
...
		System.out.println("ID= " + aMaschinendaten);
		return "goaendern";
	}

Frage:
muss ich nach dem session.load die transaktion bzw. session beenden, um danach die operation saveorUpdate oder update aufrufen zu können?

jetzt soll im formular durch betätigen des buttons speichern saveorUpdate oder update aufgerufen werden.

Code:
	public String updateMaschinendaten(){
	Session session = HibernateSessionVerwaltung.getSession();
	session.saveOrUpdate(maschinendaten);
	return "success";
}

in dieser methode hole ich mir eine neue session und will das update durchführen und beende die transaktion und session.
wenn ich aber saveOrUpdate benutze, ein objekt aus der liste auswähle, es verändere und auf speichern drücke wird immer ein neues objekt angelegt anstatt das alte zu updaten.
wenn ich update durchführe bekomme ich folgende exception:
Code:
org.hibernate.TransientObjectException: The given object has a null identifier: beans.Maschinendaten
d.h. für mich, dass das objekt unbekannt ist und sich im zustand transient befindet.

Es treten also folgende Fragen auf:
1) Muss ich nach der Operation aenderbMaschinendaten die Transaktion und Session schließen?
2) Wenn ich die Operation updateMaschinendaten starte ich eine neue Transaktion und Session und beende diese nach dem updaten wieder. ist das so richtig?

ich hoffe es ist einigermaßen verständlich was ich hier schreibe. ich werde mir jetzt noch mal in ruhe die theorie durchlesen und das kapitel objects in der hibernate-referenz angucken. Naja habe ich zwar schon oft genug gemacht, aber schlau bin ich bisher auch nicht so richtig geworden. falls jemand versteht was ich für ein problem habe, dann wäre es schön wenn er mir das kur schildern und erklären könnte....
 

happy_robot

Bekanntes Mitglied
k4lle hat gesagt.:
also wenn ich mich an das hibernate-zustandsmodell halte, dann gelangen laut meinem verständnis die persistenten objekte nachdem die session geschlossen wird in den zustand detached.
richtig. aber warum schliesst du die session?

k4lle hat gesagt.:
jetzt lade ich das (detached) objekt und möchte es updaten.
die session ist geschlossen. was willst du hier noch laden?

k4lle hat gesagt.:
wenn ich saveorUpdate benutze geschieht folgendes:

ich lade das objekt aus der DB. Zb. ein Objekt mit der ID 34. (ID wird automatisch beim Speichern zugewiesen).
Nein. saveOrUpdate lädt nichts! Es speichert ein Objekt. Wenn der primaryKey == null wird ein neues angelegt, ansonsten das mit dem primaryKey ge-"updated".

k4lle hat gesagt.:
muss ich nach dem session.load die transaktion bzw. session beenden, um danach die operation saveorUpdate oder update aufrufen zu können?
Wenn die Session beendet ist kannst Du nicht mehr auf die Datenbank zugreifen. Alle Lese- und Schreibzugriffe werden fehlschlagen. Lass die Session doch während der ganzen Sitzung geöffnet. saveOrUpdate würde ich immer in einer Transaktion aufrufen.

k4lle hat gesagt.:
jetzt soll im formular durch betätigen des buttons speichern saveorUpdate oder update aufgerufen werden.

Code:
	public String updateMaschinendaten(){
	Session session = HibernateSessionVerwaltung.getSession();
	session.saveOrUpdate(maschinendaten);
	return "success";
}

in dieser methode hole ich mir eine neue session und will das update durchführen und beende die transaktion und session.
hier holst du nur eine session und schreibst daten. es wird weder eine transaktion begonnen noch beendet

k4lle hat gesagt.:
wenn ich aber saveOrUpdate benutze, ein objekt aus der liste auswähle, es verändere und auf speichern drücke wird immer ein neues objekt angelegt anstatt das alte zu updaten.
ja...weil ein detachtes objekt immer den primaryKey null hat, welches beim schreiben dazu führt daß ein neues objekt angelegt wird. wenn du ein objekt liest und dann die session schliesst kriegen alle bisher gelesenen objekte den primaryKey null zugewiesen. deswegen: session geöffnet lassen!

k4lle hat gesagt.:
wenn ich update durchführe bekomme ich folgende exception:
Code:
org.hibernate.TransientObjectException: The given object has a null identifier: beans.Maschinendaten
d.h. für mich, dass das objekt unbekannt ist und sich im zustand transient befindet.
richtig...der primaryKey ist ja auch null. ihm fehlt ja nun der bezug auf den datensatz den er in der DB updaten soll.


k4lle hat gesagt.:
Es treten also folgende Fragen auf:
1) Muss ich nach der Operation aenderbMaschinendaten die Transaktion und Session schließen?
2) Wenn ich die Operation updateMaschinendaten starte ich eine neue Transaktion und Session und beende diese nach dem updaten wieder. ist das so richtig?
- zu beginn der anwendung die session öffnen.
- erst am ende schliessen
- alle schreiboberationen innerhalb von transaktionen (beginTransaction(), commit())
- generell saveOrUpdate nutzen (zumindest für den Anfang :) )

grüße
 

k4lle

Mitglied
ok erstmal vielen dank.

dazu muss ich folgendes sagen, was du aber natürlich nicht wissen kannst:

Code:
Session session = HibernateSessionVerwaltung.getSession();

durch die HibernateSessionVerwaltung wird die Session und die Transaktion in der Methode getSession() geladen.

ich habe mich natürlich mit einem buch beschäftigt. in diesem buch wird extra gesagt, dass man die session nach einer transaktion immer schließen soll, da ansonsten zu viel ressourcen verbraucht werden. das habe ich versucht zu berücksichtigen. scheinbar nicht mir erfolg :). wenn z.b. mehrere benutzer auf die anwendung zugreifen, ist es schlecht wenn 30 sessions gleichzeitig geöffnet sind. wie siehst du das?

so wie du mir das erklärt hast leuchtet mir das absolut ein.
- zu beginn der anwendung session öffnen
- um transaktionen durchzuführen immer transaktionen beginnen und wieder schließen
- bei beenden deranwendung session wieder schließen

wenn ich das so mache und wie bereits erwähnt 30 benutzer die anwendung gleichzeitig benutzen, ist das dann nicht eher schlecht?


PS: es muss doch möglich sein ein Objekt welches wie folgt gespeichert wird, aus der DB wieder laden zu können um änderungen durchführen zu können ?
- session starten
- transaktion beginnen
- objekt speichern
- transaktion beenden
- session beenden

Durch eine gerade gelesenen Text ist mir mittlerweile klar geworden, dass es nicht möglich ist eine objekt in einer session zu laden und in einer anderen zu verändern, bevor die erste session nicht geschlossen ist.

daraus schließe ich, wenn die erste session aber beendet wird kann ich in einer weiteren session das objekt verändern, wenn ich es an diese session binde.

wäre schön wenn du noch mal kurz was dazu sagen könntest?
 

happy_robot

Bekanntes Mitglied
also die session bei jedem zugriff zu öffnen und zu schliessen ist alles andere als sinnvoll und wird deine anwendung ganz schön ausbremsen, da dafür sehr viel zeit verloren geht. wenn du da keinen guten connection-pool hast dauert jeder zugriff etliche sekunden.

dieses buch scheint kein sehr gutes buch zu sein...........

es ist kein problem mit einer session 30 benutzern zugriff zu geben. besser wäre es aber sicherlich wenn du jedem benutzer eine eigene session gibst und sie bis zum abmelden des users geöffnet hälst also erst beim abmelden schliesst.

also so:

- Anmeldung (Session öffnen)
- n x (beginTransaction()...saveOrUpdate()....commit())
- Abmeldung (Session schliessen)

mfg
 

k4lle

Mitglied
ok, das ist leuchtet mir ein.

ich werde es jetzt so machen:

1) benutzer loggt sich ein (session wird geöffnet)
2) benutzer arbeitet mit der anwendung (transaktion geöffnet, z.b. update, transaktion geschlossen)
3) benutzer meldet sich ab (session wird geschlossen)

das bedeutet, dass ich einiges an meiner anwendung ändern muss.

ich hoffe das ist also die optimalste lösung. naja ich vertrau dir einfach mal. mir bleibt auch nichts anderes übrig, da ich bei mir so einfach nicht weiter komme und so wie du mir das erklärt hast kann ich es absolut nachvollziehen.

vielen dank. mal sehen ob später alles so läuft wie es soll. :)

PS: was passiert eigentlich wenn 2 benutzer gleichzeitig mit der anwendung arbeiten und der eine z.b. updatet und der andere kurz danach auch. kann es da zu problemen kommen? naja darum sollte ich mir vielleicht erstmal später gedanken machen....
 

happy_robot

Bekanntes Mitglied
k4lle hat gesagt.:
PS: was passiert eigentlich wenn 2 benutzer gleichzeitig mit der anwendung arbeiten und der eine z.b. updatet und der andere kurz danach auch. kann es da zu problemen kommen?
zu problemen kommt es da datenbanktechnisch nicht. das ist aber auch nicht aufgabe der datenbank dieses zu lösen. es kann ja zum beispiel sein daß du genau dieses verhalten haben willst. die DB kann davon nichts wissen. sie macht nur daß was du ihr sagst.

ich würde dir raten die ganzen zugriffe auf die datenbank in einer klasse zu kapseln statt immer die direkten methoden aufzurufen. dann kannst du dies nachher im nachhinein sehr gut koordinieren.
 

byte

Top Contributor
Ich würde mir die Session über SessionFactory#getCurrentSession() holen. Du brauchst Dir dann gar keine Gedanken über das Öffnen und Schließen der Session machen. Die Session wird automatisch beim Commit geschlossen. Über die Hibernate Konfiguration kannst Du dann die Stategie einstellen, wann eine neue Session gestartet wird, z.B. beim Zugriff durch einen neuen Thread (hibernate.current_session_context_class=thread). Noch besser: JTA mit Spring.
Die Hibernate Zustände brauchen Dich dabei eigentlich gar nicht zu kümmern (zumindest bei einfachen Dingen), denn getCurrentSession() liefert Dir immer die richtige Session, so dass Du das Objekt auch speichern kannst.

Details siehe: http://www.hibernate.org/42.html
 

k4lle

Mitglied
ok vielen dank erstmal. ich werde jetzt mal versuchen alles ein wenig zu ändern. da mir die theorie schon mal einleuchtet , müßte (hoffentlich) alles so klappen wie ich mir das vorstelle.

ich melde mich später mal und erstatte bericht.

ich finde das manchmal sehr schwierig mit büchern zu arbeiten. natürlich bekommt man da vieles erklärt, aber wenn dann mal wirklich ne frage auftaucht, dann findet man oft keine antwort. naja dazu gibt es ja zum glück foren.
 

byte

Top Contributor
Hibernate ist auch nicht umbedingt ein triviales Framework. Ich durchblicke da längst auch nicht alles. Aber die Doku auf hibernate.org ist eigentlich ganz brauchbar. Da findet man viele nützliche Hinweise, wenn man sich die Zeit nimmt, genau zu suchen. Anderes hingegen ist aber auch dort etwas knapp abgehandelt.
 

happy_robot

Bekanntes Mitglied
byto hat gesagt.:
Ich würde mir die Session über SessionFactory#getCurrentSession() holen. Du brauchst Dir dann gar keine Gedanken über das Öffnen und Schließen der Session machen. Die Session wird automatisch beim Commit geschlossen.
stimmt nicht so ganz. hibernate nutzt hier ja indirekt den standard-connection-pool der benutzten datenbank. die verbindung wird also nicht geschlossen sondern nur neu zugeteilt. das schaut bei wenigen usern ganz prima aus. wenn die anzahl der benötigten sessions größer als der pool wird, wird erst mit dem schliessen und öffnen begonnen. dann fällt die performance rapide ab.

byto hat gesagt.:
getCurrentSession() liefert Dir immer die richtige Session, so dass Du das Objekt auch speichern kannst.
ja, da die session an einen ThreadLocal gebunden ist.

das automatische öffnen und schliessen durch das framework scheint im ersten moment sehr elegant zu sein, wird aber zum krampf wenn man mal savepoints und rollbacks implementieren will.
 

k4lle

Mitglied
es geht einfach immer noch nicht meinen kopf rein was passiert wenn:

folgendes szenario ist mir klar:
- benutzer meldet sich an (session wird geöffnet)
- führt transaktionen durch (trans öffnen, z.b. update, trans schließen)
- benutzer meldet sich ab (session wird geschlossen)

aber was ist denn wenn der benutzer sich zum zweiten mal anmeldet (was natürlich der fall ist)
- benutzer meldet sich an (session wird geöffnet)
- jetzt läd er ein objekt aus der db, welches in einem form dargestellt wird und will es updaten
das klappt einfach nicht, da das geladene objekt den primary key null hat. kann ich mir auch noch vorstellen, weil es in
der session zuvor gespeichert wurde. dieses szenario muss aber möglich sein!!!!! ich habe scheinbar immer noch nicht
genau verstanden wie das funktionieren soll

- benutzer meldet sich ab (session wird geschlossen)

bisher ist es in meiner anwendung so, wenn sie gestartet wird, wird das configurations-objekt und die sessionfactory erzeugt und dann öffne ich über die sessionfactory die session.

wäre schön, wenn ihr mir noch mal was zu dem fettgeschriebene sagen könntet.
 

happy_robot

Bekanntes Mitglied
k4lle hat gesagt.:
- jetzt läd er ein objekt aus der db, welches in einem form dargestellt wird und will es updaten
das klappt einfach nicht, da das geladene objekt den primary key null hat. kann ich mir auch noch vorstellen, weil es in
der session zuvor gespeichert wurde. dieses szenario muss aber möglich sein!!!!! ich habe scheinbar immer noch nicht
genau verstanden wie das funktionieren soll
wenn du mit hibernate ein objekt aus der DB geladen hast kann es keinen null-key haben.
 

byte

Top Contributor
happy_robot hat gesagt.:
byto hat gesagt.:
Ich würde mir die Session über SessionFactory#getCurrentSession() holen. Du brauchst Dir dann gar keine Gedanken über das Öffnen und Schließen der Session machen. Die Session wird automatisch beim Commit geschlossen.
stimmt nicht so ganz. hibernate nutzt hier ja indirekt den standard-connection-pool der benutzten datenbank. die verbindung wird also nicht geschlossen sondern nur neu zugeteilt. das schaut bei wenigen usern ganz prima aus. wenn die anzahl der benötigten sessions größer als der pool wird, wird erst mit dem schliessen und öffnen begonnen. dann fällt die performance rapide ab.
Ich habe doch gar nicht von DB-Connections gesprochen sondern von Sessions. Bei getCurrentSession() wird die Session geschlossen, sobald das commit() kommt. Allerdings erzeugt Hibernate intern einen Proxy, die eigentliche Session bleibt offen je nach Strategie.

byto hat gesagt.:
getCurrentSession() liefert Dir immer die richtige Session, so dass Du das Objekt auch speichern kannst.
ja, da die session an einen ThreadLocal gebunden ist.

das automatische öffnen und schliessen durch das framework scheint im ersten moment sehr elegant zu sein, wird aber zum krampf wenn man mal savepoints und rollbacks implementieren will.
Ich habe auch nicht gesagt, dass Thread Local Sessions immer ideal sind sondern es nur als eine (einfache) Möglichkeit eröffnet. Natürlich ist es bei komplexeren Sachen sinnvoll, das anders zu machen. Dann verwendet man idealerweise Spring fürs Session und Transaction Handling und erspart sich somit viel Arbeit und Ärger.
 

k4lle

Mitglied
ja dann muss also mein fehler definitiv beim laden sein. solange eine session geöffnet ist und ich mir ein objekt aus der db lade kann es also keinen null-key haben.

User meldet sich an (Session wird geöffnet)

lade Objekt aus DB mit

Code:
Maschinendaten dieMaschinendaten = (Maschinendaten) session.load(Maschinendaten.class, aMaschinendaten);

dann muss ich jetzt ein update auf das geladene Objekt durchführen können

jetzt beendet ich die session (User meldet sich ab)

(vor allen Transaktionen wird die trans gestartet und danach beendet)


wenn das so gehen muss, dann habe ich einfach irgendwo einen fehler und muss mich einfach jetzt intensiv mit meinem programm weiter beschäftigen bis es endlich klappt.

also so muss es gehen?

diese frage noch benatworten und dann lasse ich euch erstmal in ruhe :-(
 

happy_robot

Bekanntes Mitglied
byto hat gesagt.:
Ich habe doch gar nicht von DB-Connections gesprochen sondern von Sessions. Bei getCurrentSession() wird die Session geschlossen, sobald das commit() kommt. Allerdings erzeugt Hibernate intern einen Proxy, die eigentliche Session bleibt offen je nach Strategie.
ok, die connection wird über die SessionFactory aufgebaut. die wiederum konfiguriert auch den eigenen c3p0-connection-pool, was doch nahelegt daß hier auch die verbindungen gemanaged werden und bei bedarf geöffnet oder geschlossen werden. das ist ein wenig undurchsichtig, trotzdem liegt es nahe daß jeder eigene thread eine eigene verbindung für seine sessions kriegt. und somit hast du bei 100 threads schnell immer 100-(connectionpool-size) neue verbindungen was das ganze ausbremst.

byto hat gesagt.:
Ich habe auch nicht gesagt, dass Thread Local Sessions immer ideal sind
ich auch nicht :)
 

k4lle

Mitglied
das ist genau der Integer mit dem Primary-Key. Er läd mir das ausgewählte Objekt in ein Formular.

Also habe ich mit meinem letzten post recht?
wenn ich damit recht habe, dann weiß ich zumindest was ich zu tun habe. Ansonsten habe ich kein Bock mehr und schmeiß den ganzen scheiß weg ;-)
 

byte

Top Contributor
happy_robot hat gesagt.:
byto hat gesagt.:
Ich habe doch gar nicht von DB-Connections gesprochen sondern von Sessions. Bei getCurrentSession() wird die Session geschlossen, sobald das commit() kommt. Allerdings erzeugt Hibernate intern einen Proxy, die eigentliche Session bleibt offen je nach Strategie.
ok, die connection wird über die SessionFactory aufgebaut. die wiederum konfiguriert auch den eigenen c3p0-connection-pool, was doch nahelegt daß hier auch die verbindungen gemanaged werden und bei bedarf geöffnet oder geschlossen werden. das ist ein wenig undurchsichtig, trotzdem liegt es nahe daß jeder eigene thread eine eigene verbindung für seine sessions kriegt. und somit hast du bei 100 threads schnell immer 100-(connectionpool-size) neue verbindungen was das ganze ausbremst.
Den Connection Pool kannst Du ja über die Hibernate Config definieren. Die wird dann über die SessionFactory geladen, das ist richtig.
Aber Du hast glaube ich einen Denkfehler (oder ich verstehe Dich falsch ;) ): Es besteht keine 1:1 Beziehung zwischen Hibernate Session und DB-Connection! Der Common Way ist das Session-Per-Request Pattern (siehe hier). Häufig wird jeder Request in einem eigenen Thread bearbeitet, das heisst jeder Request wird in einem Thread mit einer Session in einer Transaktion abgehandelt. Das heisst aber nicht zwangsläufig, dass auch jede Session eine eigene DB-Connection bekommt.

Hibernate Doku hat gesagt.:
A Session is an inexpensive, non-threadsafe object that should be used once, for a single request, a conversation, single unit of work, and then discarded. A Session will not obtain a JDBC Connection (or a Datasource) unless it is needed, hence consume no resources until used.
 

happy_robot

Bekanntes Mitglied
byto hat gesagt.:
Aber Du hast glaube ich einen Denkfehler (oder ich verstehe Dich falsch ;) ): Es besteht keine 1:1 Beziehung zwischen Hibernate Session und DB-Connection!
das ist schon klar :)

mir ging es darum daß du nicht unbedingt darauf vertrauen solltest das bei getCurrentSession() nicht doch auch wieder eine neue verbindung aufgemacht wird. wenn du mehr threads hast als im pool liegen geht der ärger los.

ich mache es zum beispiel immer so daß ich eine vorher definierte anzahl an verbindungen öffne (1-n) und die kandidaten die an die datenbank wollen können sich jeweils eine vebindung abholen. diese wird dann mittells semaphore gesperrt bis der zugriff abgeschlossen ist und der nächste der dran will muss solange an der semaphore warten. lässt sich prima loggen und koordinieren. auf automatismen zu vertrauen habe ich mir hier abgewöhnt.

das fragment aus der hibernate-doku erstaunt mich etwas. bei mir klappt das ganz prima.
 

happy_robot

Bekanntes Mitglied
k4lle hat gesagt.:
happy sag bitte noch mal was zu meinem letzten poste :)
wenn da eine not-null id als primary-key drin steht is doch alles gut.
wenn jetzt allerdings die session geschlossen ist schlägt ein update in jedem falle fehl.
in der session in der du das ding geladen hast muss auch das update erfolgen.
 

k4lle

Mitglied
jetzt weiß ich wo das problem genau liegt. zum testen speichere ich nach dem start der anwendung mehrere objekte. das klappt auch ohne weiteres. alle operationen öffnen und schließen nur transaktionen. die session schließe ich beim abmelden.

Operation zum öffnen der Session
Code:
	public Session oeffneaktuelleSession(){
		aktuelleSession = HibernateSetup.getSessionFactory().openSession();
		return aktuelleSession;
	}

Operation zum speichern der objekte
Code:
	public String saveMaschinendaten(){
		Transaction transaction = oeffneaktuelleSession().beginTransaction();
		System.out.println("Transaction gestartet");
		aktuelleSession.save(maschinendaten);
		transaction.commit();
		return "success";
	}

Operation zum laden eines Objekts, welches in einem Formular dargestellt wird.
Code:
public String aendernMaschinendaten(){
		System.out.println("ID= " + aMaschinendaten);
		Transaction transaction = oeffneaktuelleSession().beginTransaction();
		Maschinendaten dieMaschinendaten = (Maschinendaten) aktuelleSession.load(Maschinendaten.class, aMaschinendaten);
		maschinendaten.setBetriebsmittel(dieMaschinendaten.getBetriebsmittel());
		maschinendaten.setDokumentation(dieMaschinendaten.getDokumentation());
		maschinendaten.setSiehe(dieMaschinendaten.getSiehe());
                ...
                ...
		transaction.commit();
		return "goaendern";
	}

Wird aufgerufen wenn im formular speichern gedrückt wird
Code:
	public String updateMaschinendaten(){
		Transaction transaction = oeffneaktuelleSession().beginTransaction();
		aktuelleSession.saveOrUpdate(maschinendaten);
		transaction.commit();
		return "success";
	}

das laden aus der db klappt nicht richtig. es passiert immer folgendes. egal ob ich update oder saveorupdate benutze. um das zu verdeutlichen beschreibe ich das mal.
- Ich speichere 2 Objekte ab mit folgenden Werten (nur als beispiel)
1) ID = 1, Name = Tim, Alter = 23
2) ID = 2, Name = Christian, Alter = 24
- Jetzt lade ich mir durch die aendernMaschinendaten() ein objekt aus der DB. ich will das 1) objekt laden. hierzu lasse
ich mir zum test mit System.out.println(aMaschinendaten); die ID ausgeben. Es wird die ID = 1 angezeigt und
schließlich das objekt in einem formular angezeigt. bis dahin ist alles wunderbar.
- jetzt will ich das geladene objekt verändern und die updateMaschinendaten() aufrufen.
Es passiert aber immer folgendes. Obwohl das 1 Objekt geladen ist (meiner meinung nach), wird beim aufruf der
methode updateMaschinendaten() immer nur das zuletzt durch die methode saveMaschinendaten() gespeicherte
Objekt verändert. in diesem fall wird also das Objekt 2 geupdatet, da dieses zuletzt gespeichert wurde.

Wieso ist das so? Mache ich beim Laden etwas falsch? Ich hoffe das ist verständlich und Ihr Profis könnt mir schnell dazu was sagen. Jetzt öffne ich nur eine Session und trotzdem klappt das nicht richtig. Wo mache ich denn was falsch?[/quote]
 

ms

Top Contributor
In allen deinen Codesnippets, die du angeführt hast, erzeugst du jedesmal eine neue Session.
byto hat oben schon gesagt, dass es SessionFactory.currentSession() gibt um die aktuelle Session zu bekommen.

Übrigens wurde meine Frage von oben bisher noch nicht beantwortet.
Ich gehe jetzt mal davon aus, dass wir hier von einer Webapplikation reden.

k4lle hat gesagt.:
- jetzt will ich das geladene objekt verändern und die updateMaschinendaten() aufrufen.
Bitte erkläre ganz genau was du mit 'verändern' meinst.
Sind das zwei verschiedene Requests?

ms
 

k4lle

Mitglied
ok. ich rufe ja auch immer die oeffneaktuelleSession() auf und dort wird dann immer wieder eine neue session erzeugt. so will ich das natürlich nicht.
es geht hier um eine webapplikation.

also session öffnen und dann kann ich mittels SessionFactory.currentSession jeder Zeit auf die aktuelle Session zugreifen.

ich benutze JSF, lade mir über einen dataTable mein ausgewähltes objekt in ein formular und will dann durch betätigen eines buttons in Hibernate saveOrUpdate() oder update() ausführen. durch betätigen wird die action-methode updateMaschinendaten() aufgerufen, welche die Hibernate Transaction durchführt.

also kann es bisher nur daran liegen, dass ich immer wieder neue sessions geöffnet habe?
 

ms

Top Contributor
Es reicht, wenn du immer SessionFactory.currentSession() aufrufst. Diese Methode kümmert sich schon um das erstmalige Öffen der Session.

Code:
public String aendernMaschinendaten(){
      System.out.println("ID= " + aMaschinendaten);
      Transaction transaction = oeffneaktuelleSession().beginTransaction();
      Maschinendaten dieMaschinendaten = (Maschinendaten) aktuelleSession.load(Maschinendaten.class, aMaschinendaten);
      maschinendaten.setBetriebsmittel(dieMaschinendaten.getBetriebsmittel());
      maschinendaten.setDokumentation(dieMaschinendaten.getDokumentation());
      maschinendaten.setSiehe(dieMaschinendaten.getSiehe());
                ...
                ...
      transaction.commit();
      return "goaendern";
   }
Hier fällt mir nur auf, dass es zwei Variablen vom Typ Maschinendaten gibt.
Allerdings wird nicht die geladene (dieMaschinendaten) geändert sondern die andere (maschinendaten).

ms
 

k4lle

Mitglied
also wenn ich SessionFactory.getCurrentSession() benutze muss ich mich um nichts kümmern außer vor den DB-Transaktionen die transaction zu beginne und danach zu beenden. ist das soweit richtig?
 

byte

Top Contributor
Ja, das habe ich oben doch schon geschrieben. Im übrigen würde ich Dir für Webanwendungen das Open Session in View Pattern ans Herz legen (eine Transaction pro Request). Das kombinierst Du am besten mit dem DAO Pattern, dann wird Dein Code auch etwas logischer und man findet leichter Fehler (eine Methode aendernMaschinendaten(), die Klassenvariablen per Hibernate in die DB schreibt, ist großer BS, sorry ;) ).
 

k4lle

Mitglied
kein problem. kannst du ruhig sagen. ich kann das bloß jetzt nicht mal eben immer wieder alles ändern. fürs nächste mal weiß ich bescheid. ich habe mich halt bisher nur an bücher gehalten. und da wird es so gemacht wie ich es versuche.

naja ich mach mal weiter. ich habe zwar keine hoffnung mehr, aber da muss man wohl durch. ich hoffe spätestens morgen klappts. ansonsten schlag ich alles kaputt.
 

k4lle

Mitglied
So jetzt klappt endlich alles so wie ich mir das vorgestellt habe. Als kleines Beispiel möchte ich euch mal eine Methode zeigen und ihr sollt sagen was ich vielleicht beim nächsten mal anders machen sollte. Außerdem wäre ich euch sehr verbunden, wenn ihr mir noch mal die genau Funktionsweise von getCurrentSession() erklären könnt. Natürlich verstehe ich was bisher dazu geschrieben wurde, aber falls es noch ein weinig detaillierter geht wäre das super.

Code:
	public String saveMaschinendaten(){
		Session session = null;
		Transaction transaction = null;
		try {
			session = HibernateSetup.getSessionFactory().getCurrentSession();
			transaction = session.beginTransaction();
			session.save(maschinendaten);
			transaction.commit();
		}
		catch(HibernateException e){
			if (transaction != null) {
				transaction.rollback();
				throw e;
			}
		}
		return "success";
	}

Vielen Dank für alle Hilfe. Wenigstens habe ich jetzt eine Basis, auf der ich aufbauen kann.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
F Problem mit Hibernate Schema Update Data Tier 2
N Hibernate - Problem mit Update/Insert Data Tier 4
G Hibernate select update no wait Data Tier 8
A JPA/Hibernate: Update/Delete/Insert auf Entities von DB-Views Data Tier 3
M Hibernate: Skalare Funktionen und Update Data Tier 6
S Hibernate: Dauer-Update bei composite-element Data Tier 6
I Hibernate / JPA: Eine Datenbank und pro User ein Schema Data Tier 9
T Hibernate/Spring JPA: eigene ID generieren Data Tier 5
Avalon @ManyToOne Hibernate oder JPA? Data Tier 5
D Hibernate Hibernate mit MariaDB Data Tier 1
ToBJo Hibernate Glassfish deploy mit Hibernate schlägt fehl Data Tier 1
C JPA Hibernate Map<String,String> richtig mappen Data Tier 2
S JPA Hibernate Search & EclipseLink (oder OpenJPA) Data Tier 0
R JPA Probleme mit Wechsel von EclipseLink auf Hibernate Data Tier 4
ARadauer Hibernate Entität readonly laden... Data Tier 1
G Hibernate SQL in Hibernate: Keine Parameter mit Index? Data Tier 2
P Wildfly + Hibernate + SQL Server Data Tier 0
E JPA Hibernate Query mit Timestamp hat seltsames Verhalten Data Tier 1
M Eclipse 4 RCP Hibernate Problem Data Tier 3
C Hibernate ProgressBar updaten mit Daten aus Hibernate Data Tier 4
B Hibernate und MySQL testen Data Tier 8
I Hibernate HQL: generiertes SQL ausgeben Data Tier 1
R mapping-file für hibernate zum Überschreiben der Annotationen Data Tier 7
R Hibernate Hibernate und Logback Data Tier 2
R Hibernate möchte Schema zwei mal undeployen Data Tier 2
F Hibernate Hibernate / JPA Data Tier 4
E Hibernate: Session vs EntityManager Data Tier 3
C Hibernate Hibernate Code Generation Data Tier 3
S Hibernate Mehrfachverbindung mit Hibernate Data Tier 3
M Hibernate Einstiegsfrage Data Tier 5
M Exception in thread "main" org.hibernate.MappingException: java.lang.ClassNotFoundException: Message Data Tier 4
S Hibernate Einstieg in Hibernate 3.2 sinnvoll? Data Tier 8
P JPA Eigene Vererbungsstrategie mit JPA / Hibernate Data Tier 2
J Hibernate Problem bei Master-Detail-Tabellen Data Tier 5
Y Jboss seam-hibernate-jpa Data Tier 5
RaoulDuke Hibernate Map<String,String> mit Annotations mappen Data Tier 2
M Hibernate Hibernate with GWT Data Tier 4
C Hibernate JPA mysql db erstellen Data Tier 4
M Hibernate Hibernate liest Daten zu oft aus! Data Tier 16
pg1337 Hibernate Fragen Data Tier 11
D Probleme bei Left Joins mit Hibernate createCriterias() Data Tier 2
D Hibernate probleme mit Verlinkungstabelle Data Tier 4
2 Hibernate Annotations Data Tier 7
Z Hibernate: Many-To-Many nur eine bestimmte Spalte Data Tier 3
K Hibernate - Envers - Erzeugung der SQL Skripte Data Tier 4
G Hibernate 1:n Beziehung mit Vererbung Data Tier 5
D Hibernate-Criteria-API (Projections und MAX-Funktion) Data Tier 6
L Hibernate: failed to lazily initialize a collection of role Data Tier 3
S Hibernate hibernate.cfg.xml Data Tier 14
D JPA vs Hibernate.cfg und Entitymanager Data Tier 6
H Hibernate - Mapping für Enumeration Data Tier 1
R Hibernate Criteria Abfrageproblem Data Tier 2
A Hibernate und jdbc zusammen Data Tier 4
D Mit Hibernate aus JUnit ein DB-Schema erzeugen Data Tier 6
S [Hibernate] No Persistence provider for EntityManager Data Tier 5
B Problem mit org.hibernate.LazyInitializationException Data Tier 11
G Hibernate HQL und Interface Data Tier 4
G JSF Hibernate no session or session was closed Data Tier 12
T JPA2/Hibernate: Many-to-Many-Relation wird u.a. beim löschen nicht aktualisiert Data Tier 14
S (Hibernate) Mapping einer Datenbanktabelle mit mehreren Fremdschlüssel Data Tier 7
X [Hibernate] Zusammengesetzte Entities möglich? Data Tier 7
N Hibernate Fake? Data Tier 2
S Problem beim Insert mit Hibernate Data Tier 9
V Hibernate Projection Data Tier 2
T org.hibernate.impl.SessionFactoryImpl Memory Leak Data Tier 10
G Hibernate Composite key Data Tier 11
X [Hibernate] Connection Pool - MinSize ? Data Tier 2
R Hibernate Criteria OR Data Tier 2
T hibernate/jpa abgefragte Listen immer mit Null-Werten gefüllt Data Tier 8
X [Hibernate] Anderen Connection Pool - Vorschläge? Data Tier 3
ARadauer Hibernate DDL Loggen Data Tier 6
G Hibernate abfrage Collection Data Tier 3
X [Hibernate] ReverseEngineering - Eigene Strategy verwenden? Data Tier 3
R Hibernate Criteria .group größer als Data Tier 5
R Hibernate daten laden Data Tier 7
H [Hibernate]1:1 Beziehung Data Tier 8
H [Hibernate]No CurrentSessionContext configured! Data Tier 6
X [Hibernate] Lässt sich die Dauer eines SELECTs loggen? Data Tier 4
R Hibernate n:n Relationtabelle mit Date Data Tier 3
H [Hibernate] Unknown Entity Data Tier 3
H [Hibernate] Configuration Data Tier 3
C [Hibernate] Generierung von hbm.xml to Java Data Tier 4
lumo Eclipse & JPA & Hibernate & Derby Data Tier 5
J Zufallsauswahl aus ResultList bei JPA(Hibernate) / Performance Data Tier 3
M Hibernate: Datum 0001-01-01 erzeugt null-Datum Data Tier 4
G Datenbankzugriff mit Hibernate Data Tier 7
Y Hibernate - Angabe des Schemas Data Tier 6
LadyMilka (Hibernate) in Criteria implizierter Join durch Subquery's Data Tier 8
M Hibernate Mehr als 1 Object speichern? Data Tier 18
M Unerklärliche Hibernate Exception Data Tier 20
LadyMilka (Hibernate) subquery in FROM-Clause Data Tier 9
haemi Viele DTOs in hibernate IdentityMap Data Tier 3
LadyMilka (hibernate) UNION dem Dialekt hinzufügen Data Tier 3
M Hibernate + Oracle 10g XE Data Tier 3
lumo Hibernate - entity class not found Data Tier 5
P SQL PRoblem Hibernate? Data Tier 8
J Vererbung mit JPA / Hibernate - pro/contra Data Tier 3
T JBoss/Hibernate: Abfrage dauert lang + hohe CPU? Data Tier 19
7 Hibernate-Abfrage (SubSelect im FROM) Data Tier 2
G Hibernate: many-to-one - Verwaiste Datensätze löschen Data Tier 2

Ähnliche Java Themen


Oben