-->
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.  [ 5 posts ] 
Author Message
 Post subject: Reattach ohne SELECT oder UPDATE
PostPosted: Sun Apr 25, 2010 7:23 am 
Beginner
Beginner

Joined: Sun Apr 25, 2010 7:14 am
Posts: 30
Hallo zusammen,

ich beschäftige mich seit einiger Zeit mit Hibernate und bin gerade dabei eine etwas größere Webanwendung damit zu realisieren.
Allerdings macht mir dabei das Wiederanbinden eines Objektes an die Session Probleme (session-per-request).

Ein Benutzer loggt sich im System ein, ich erstelle das User-Bean und lege es in der Session ab. Am Ende des Requests wird
das Objekt von der Session getrennt. Nun muss ich bei jedem Request das Objekt wieder verbinden, da es sonst zu Fehlern beim
Zugriff auf die Relationen kommt.

session.update(user):
Würde funktionieren, führt aber immer einen Update aus, der z.B. das Versionsattribut verfälscht. Wäre man mit 2 Browsern als
der gleiche User eingeloggt, würde es ständig zu Fehlern kommen, weil das Bean outdated ist.

session.merge(user):
Führt ständig SELECTs aus um zu prüfen ob sich das Objekt verändert hat (???). Das Objekt wird im dettached Zustand nicht verändert.
Ein SELECT für den User an sich wäre noch zu verkraften... es werden aber auch scheinbar für alle Relationen SELECTs ausgeführt
und das ist einfach zu viel. Außerdem ist hier noch das Problem, das nicht das Objekt selbst sondern eine Kopie mit der Session
verknüpft wird. Ich muss also ständig das Sessionattribut austauschen.

Gibt es keine Möglichkeit das Objekt mit der Session zu verbinden (damit der Zugriff auf die Relationen funktioniert) ohne dabei
unzählige UPDATEs oder SELECTs auszuführen? Schließlich könnte ich mir es dann ja auch sparen das Objekt in der Session abzulegen
und es einfach für jeden Request neu erzeugen.

Danke für eure Hilfe.

Grüße
Thomas


Top
 Profile  
 
 Post subject: Re: Reattach ohne SELECT oder UPDATE
PostPosted: Mon Apr 26, 2010 6:54 am 
Beginner
Beginner

Joined: Sun Apr 25, 2010 7:14 am
Posts: 30
Ich habe gerade bemerkt, dass lock() mit LockMode.NONE eigentlich genau das ist, was ich will. Reattach ohne unnötige Queries.
Warum ist diese Methode deprecated bzw. was ist die Alternative?

Grüße
Thomas


Top
 Profile  
 
 Post subject: Re: Reattach ohne SELECT oder UPDATE
PostPosted: Fri Aug 13, 2010 8:39 am 
Newbie

Joined: Tue May 26, 2009 6:01 am
Posts: 3
Location: Hannover, Germany
Hallo Thomas,

vielleicht beschäftigst Du Dich inzwischen schon mit einem ganz anderen Problem oder hast schon längst selber die Lösung gefunden. Schau Dir mal in den API-Docs (http://docs.jboss.org/hibernate/stable/core/api/) die Klasse Session an. Dort gibt es eine Methode buildLockRequest(LockOptions lockOptions). Diese liefert Dir ein Objekt vom Typ LockRequest auf welchem Du dann lock(<Dein Entity>) aufrufen kannst.

Zu dem Thema hätte ich jetzt einmal eine andere Frage an Dich: Bist Du schon einmal über eine org.hibernate.HibernateException mit dem Fehlertext "reassociated object has dirty collection" beim Aufruf von session.lock() gestolpert. Bei mir tritt die Situation auf, wenn ein Entity A eine One-To-Many-Assoziation zu einem Entity B hat. Mit einem JPQL selektiere ich nun ein A, ohne die Assoziation zu B mittels Join-Fetch einzuschließen. Durch einen separaten JPQL selektiere ich alle B, die mit diesem einen A assoziiert sind. (Dies kann ich, da ich die Foreign-Key-Spalte aus der Tabelle von B im Entity B durch ein eigenes Attribut abbilde. Wenn dieses Attribut insertable = false und updatable = false ist, dann ist der lesende Zugriff auf dieses FK-Attribut kein Problem.)

Die Assoziation zwischen A und B instanziiere ich manuell wie folgt:

Code:
String[] parameterNamen = new String[] {"aId"};
Object[] parameter = new Object[] {aId};

A a = this.executeNamedQuerySingleResult(A.class, ejbQlStringFuerA, parameterNamen, parameter); // EJBQL: select a from A a where a.aId = :aId
List<B> listOfB = this.executeNamedQueryMultipleResult(B.class, ejbQlStringFuerBs, parameterNamen, parameter); // EJBQL: select b from B b where b.aId = :aId

a.setB(listOfB); // <-- Dies ist die manuelle Instanziierung der Assoziation!


Würde ich nun flushen, dann würde Hibernate für alle B in der Assoziation ein Update erzeugen. Kann ich auch nachvollziehen, da Hibernate diese Assoziation nicht selber initialisiert habe und der EntityManager gar nicht wissen kann, ich bei meiner manuellen Instanziierung die richtigen Entities in die Assoziation gesteckt habe. Diesen Flush lasse ich aber Hibernate gar nicht ausführen, indem ich einfach einen Detach durchführe:

Code:
session.clear();


Das Problem ist nun ähmlich wie Deins. Wenn ich meine Entities reattache, indem ich session.merge() aufrufe, dann gibt es erst einmal eine Reihe von Updates für alle B, die in der Assoziation stecken. Kann ich auch verstehen: Hibernate merkt, dass die assoziierten Objekte in einer "normalen" List und nicht in einer PersistentCollection stecken. (Hibernate verpackt assouiierte Objekte ja üblicherweise immer in einer solchen PersistenCollection.) Es könnten in dieser nicht von Hibernate erzeugten List Entities enthalten sein, zu denen noch gar keine FK-Beziehungen in der Datenbank gespeichert sind. Demzufolge müssen also diese SQL-Updates beim Merge durchgeführt werden.

Ich hatte nun aber gehofft, dass ich diese aus meiner Sicht unnützen SQL-Updates vermeiden kann, indem ich einfach session.lock(a, LockMode.NONE) aufrufe. Gemäß Dokumentation wird beim Setzten des Lock-Modes ein Entity zwar reattached, aber sein Zustand nicht sofort mit der Datenbank synchronisiert. Leider wirft Hibernate besagte HibernateException, wenn ich meine Assoziation auf die oben beschriebene Weise instanziiert habe. Wenn die assoziierten Objekte nicht non einer PersistentCollection gehalten werden, dann weigert sich Hibernate die Objekte mit session.lock() zu attachen.

Ist Dir dieses Problem bei Deiner Arbeit auch über den Weg gelaufen? Hast Du evtl. einen Lösungsansatz gefunden, der weder eine Exception, noch unnötige SQL-Updates zur Folge hat? Falls Du Ideen zu dem Thema hast, dann würde ich mich über ein Feedback freuen!

Viele Grüße
Max


Top
 Profile  
 
 Post subject: Re: Reattach ohne SELECT oder UPDATE
PostPosted: Tue Sep 07, 2010 10:35 am 
Beginner
Beginner

Joined: Sun Apr 25, 2010 7:14 am
Posts: 30
Hi Max,

danke auf die Lösung mit buildLockRequest bin ich auch noch gestoßen und funktioniert soweit auch ganz ok.

Leider kann ich dir aber bei deinem Problem nicht helfen... habe leider auch die Erfahrung gemacht, dass es generell sehr wenig
Hilfe bei solchen "fortgeschrittenen" Problemen in Bezug auf Hibernate gibt :(

Grüße
Thomas


Top
 Profile  
 
 Post subject: Re: Reattach ohne SELECT oder UPDATE
PostPosted: Tue Sep 21, 2010 2:33 pm 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
I can't believe people write in german..


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 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.