-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 
Author Message
 Post subject: Refresh Problem bei mehrfachem Aufruf einer Query
PostPosted: Fri Sep 29, 2006 3:13 am 
Newbie

Joined: Mon Oct 10, 2005 6:10 am
Posts: 10
Hibernate version:
3.1

Hallo zusammen,

hat jemand eine Idee, wie ich möglichst effizient eine (grosse) Menge an Objekten aktualisieren kann?
Hintergrund:
In einer Rich-Client-Anwendung sollen u.a. Stammdaten in Listen angezeigt werden. Das Vorgehen hierbei (siehe auch Code-Beispiel):
1. Session anlegen
2. Transaktion beginnen
3. Query erzeugen und Liste von dieser abholen
4. Transaktion enden

Die erhaltene Liste soll nun aktualisiert werden, d.h. Query an die Datenbank schicken, so dass alle bereits vorhandenen Objekte mit dem neuesten Stand aus der Datenbank gefüllt sind und potentiell neue Objetke mit in die Liste aufgenommen werden. Dazu wird wieder wie oben beschrieben vorgegangen. Leider werden bei erneuten Suchvorgängen bereits in der Session bekannte Objekte nicht aktualisiert, ihr Zustand bleibt unverändert (siehe Ergbnis, alle Objekte mit ID 1..4 sind nicht aktualisiert worden. Im Codebeispiel wurde absichtlich zuerst nur ein Teilmenge in der ersten Query angefordert, damit in der Ergebnisausgabe die unterschiedlichen Zustände deutlicher werden.).

Configuration
Code:
Configuration cfg = new Configuration().addFile(...);
cfg.setProperty("hibernate.cache.use_second_level_cache","false");

Mapping documents:
Code:
<class name="TestA" table="testa">
      <id name="id"> <generator class="assigned"/></id>
      <version name="changenumber" unsaved-value="null" type="java.lang.Long"/>
      <property name="textA"/>
      <property name="textB"/>
      
   </class>


TestA.changenumber wird bei updates durch die DB um 1 erhöht (Trigger).

Code between sessionFactory.openSession() and session.close():
Code:
Session session = ...
Transaction tx = session.beginTransaction();
//Laden einer Teilmenge von TestA
List<TestA> list = (List<TestA>) session.createQuery("from TestA item where item.id<5").list();
tx.commit();

//Simulation von Aenderungen an der Gesamtmenge von TestA durch einen anderen Thread
Connection con = ....getConnection();
con.createStatement().executeUpdate("update testa set texta='after' ");
con.commit();
con.close();
//Ende Simulation

//hier potentielles Aktualisieren der bereits in Liste list vorhandenen Objekte - siehe Codebeispiel weiter unten - durch session.refresh(...)

//Erneutes Laden, diesmal jedoch die Gesamtmenge von TestA
tx = session.beginTransaction();
List<TestA> list2 = (List<TestA>) session.createQuery("from TestA ").list();


for (TestA item:list2) {
   System.out.println(item.getId()+"|"+item.getChangenumber());
}

Ergebnis:
id | text | changenumber
1|before|1
2|before|1
3|before|1
4|before|1
5|after|2
6|after|2
7|after|2
Das Problem lässt sich sehr leicht lösen, indem ich ALLE bereits vorhandenen Objekte vor oder auch nach dem erneuten Absetzen einer Query durch Session.refresh(item) aktualisiere.
Code:
for (TestA item:list){
  session.refresh(item);
}
...
Ergebnis :
id | text | changenumber
1|after|2
2|after|2
3|after|2
4|after|2
5|after|2
6|after|2
7|after|2


Beim jedem Aufruf von session.refresh(...) wird jedoch (soweit ich es nachvollzogen habe) immer ein SQL-Statement gegen die Datenbank geschickt. Das führt also bei rel. mächtigen Mengen an Objekten zu einer enormen und vor allem nicht notwendigen Last und erhöhten Gesamtdauer der Aktualisierung.

Gibt es die Möglichkeit, der Session mitzuteilen, dass bei einer Query auch bereits vorhandene Objekte mit den "neuen" Werten aktualisiert werden sollen? Oder sind nur die beiden Alternativen vorhanden:
a) für jedes bereits in der Session bekannte Objekt ein session.refresh(objekt) aufrufen
b) alle bereits vorhandenen Objekte aus der Session entfernen (evict) und neue Objekte durch die Query erzeugen lassen, mit dem Nachteil, dass alle Referenzen auf die "alten" und entfernten Objekte ungültig werden (aus der Gui, etc.)

Für jeden Hinweis bin ich dankbar!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 20, 2006 10:05 am 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
Die Session wird nicht einfach so mal die Objekte neu lesen. Statt session.refresh würde ich eher die session schließen, eine neue öffnen und die Daten über eine Query holen.

Bei 2000 Einträgen sind das 1 Statement statt 2000

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


Top
 Profile  
 
 Post subject: Re: Refresh Problem bei mehrfachem Aufruf einer Query
PostPosted: Tue Nov 07, 2006 2:50 pm 
Beginner
Beginner

Joined: Thu Jun 29, 2006 12:36 pm
Posts: 20
jojan wrote:
b) alle bereits vorhandenen Objekte aus der Session entfernen (evict) und neue Objekte durch die Query erzeugen lassen, mit dem Nachteil, dass alle Referenzen auf die "alten" und entfernten Objekte ungültig werden (aus der Gui, etc.)


Hi, ich wollte mich erkundigen, ob du dazu eine Lösung gefunden hast?

Ich sitze im Moment vor genau dem gleichen Problem. Ich hab eine RCP Anwendung in der verschiedene Views auf das gleiche Model zugreifen. Hole ich mir durch ein erneutes Query die aktuellen Daten zu den Objekten erhalte ich neue Instanzen der Objekte und verliere die Verknüpfungen zum GUI.

Falls du eine Lösung gefunden hast, wäre ich dir sehr dankbar, wenn du sie hier mitteilen könntest.

Grüße
Pyoeter


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 08, 2006 4:21 am 
Newbie

Joined: Mon Oct 10, 2005 6:10 am
Posts: 10
Mein derzeitiger Wissensstand ist (und ich lasse mich sehr gerne eines besseren belehren, denn das würde eingige Probleme lösen ;-) )

Sobald ein Objekt im first-level Cache einer Session vorhanden ist, kann es nur noch individuell aktualisiert werden (Session.refresh(instanz), Session.xyz(instanz)).

Vermutung (noch nicht getestet): auch der "Umzug" eines Objektes von einer Session s1 zu s2 (mit s1.close und z.Bsp. s2.lock(Instanz)) führt zum selben Verhalten.

Für alle Rich-Client (Fatclient) Entwickler hat dieses Verhalten die Konsequenzen:

a) die Applikation so entwerfen, dass es kein Problem ist, Objekte häufig wegzuwerfen und neu zu erzeugen, die sich auf dieselbe DB-Entität beziehen (Kunde Müller, vor der der Aktualisierung der Daten Instanz K1, nach der Aktualisierung der Daten K2). Dies ist insbesondere bei GUIs eine Herausforderung. Achtung: Der Kunde Müller wird hier in einer Tabelle, einem Baum, einer Liste mit 500 .. 1000 weiteren Kunden angezeigt. Um die gesamte Kundenliste zu aktualisieren ohne alle Instanzen vorher wegzuwerfen, müsste also jedes Kundenobjekt individuell aktualisiert werden.

b) Hibernate zum "Datenlieferant" reduzieren (vgl. hierzu Data Transfer Objects Pattern (DTO)) und das GUI-Datenmodell von Hibernate entkoppeln: Hibernate erzeugt DTO-PoJos, deren Inhalt in GUI-Datenmodellobjekte irgendwie "übertragen" wird. Die DTO-PoJos können danach weggeworfen werden.


Grüße Jochen


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 08, 2006 6:49 am 
Senior
Senior

Joined: Fri May 14, 2004 9:37 am
Posts: 122
Location: Cologne, Germany
jojan wrote:
b) Hibernate zum "Datenlieferant" reduzieren (vgl. hierzu Data Transfer Objects Pattern (DTO)) und das GUI-Datenmodell von Hibernate entkoppeln: Hibernate erzeugt DTO-PoJos, deren Inhalt in GUI-Datenmodellobjekte irgendwie "übertragen" wird. Die DTO-PoJos können danach weggeworfen werden.


Also das wird bei uns etwas anders gelöst. Wir benutzen normalerweise die POJO's auch als DTO bzw. VO für eine RCP (Eclipse-RCP)Anwendung, nur unter ganz bestimmten Umständen verwenden wir spezielle DTO Objekte. Zum Clientseitigen Rendern, Validieren und Aktualisieren der Modelle verwenden wir Raptor. Hierbei laden wird die Objekt so, das nur die Relevanten Daten dann zur Laufzeit nach oder lassen diese mittels JMS zum Client pushen. Interessant könnte in nächster Zeit DataBinding von Eclipse werden, da hiermit MVC einfacher werden könnte.

_________________
regards

Olaf

vote if it helped


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 08, 2006 7:25 am 
Newbie

Joined: Mon Oct 10, 2005 6:10 am
Posts: 10
Kaneda wrote:
jojan wrote:
Zum Clientseitigen Rendern, Validieren und Aktualisieren der Modelle verwenden wir Raptor. Hierbei laden wird die Objekt so, das nur die Relevanten Daten dann zur Laufzeit nach oder lassen diese mittels JMS zum Client pushen


Raptor? wo finde ich weitere Informationen hierzu?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 10, 2006 7:05 am 
Senior
Senior

Joined: Fri May 14, 2004 9:37 am
Posts: 122
Location: Cologne, Germany
Raptor findest Du hier http://raptor.xcom.de/wiki.jz .

_________________
regards

Olaf

vote if it helped


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 27, 2006 4:43 pm 
Newbie

Joined: Mon Jan 05, 2004 11:04 am
Posts: 16
Hallo,

schaut euch mal den Link

http://blog.hibernate.org/cgi-bin/blosxom.cgi/Christian%20Bauer/java/hibernateswing.html

zum Thema Fat-Client an.

_________________
_________________
Siegbert

Please don't forget to give credit if/when you get helpful information.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 27, 2006 5:24 pm 
Beginner
Beginner

Joined: Thu Jun 29, 2006 12:36 pm
Posts: 20
Dankeschön für den Link!

Auf das versprochene Tutorial von Christian habe ich schon lange gewartet. Sobald ich mehr Zeit habe, werde ich mir den Quelltext dazu mal genauer ansehen.

Ich hoffe, dass es bald mehr Infos über Best Practices in einer Hibernate-Rich-Client-2-Schichten-Architektur gibt. Wäre meiner Meinung nach dringend notwendig. Alles was man bisher findet, sind viele Ideen aber noch kein Konsens.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 28, 2006 5:19 am 
Senior
Senior

Joined: Fri May 14, 2004 9:37 am
Posts: 122
Location: Cologne, Germany
Im neuen Eclipse Magazin gibt es einen Artikel zum Thema Hibernate und RichClient, leider hatte ich noch nicht die Zeit mir den Artikel zu Gemüte zu führen, aber ich denke die Jungs zeigen vielleicht auch in die richtige Richtung.

_________________
regards

Olaf

vote if it helped


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.