-->
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.  [ 7 posts ] 
Author Message
 Post subject: LazyLoading reload über DB-Zugriff konfigurieren
PostPosted: Mon Feb 13, 2012 5:29 am 
Newbie

Joined: Mon Feb 13, 2012 4:43 am
Posts: 4
Hallo Hibernate Gemeinde,

ich möchte meine LazyLoading Beziehungen so konfigurieren, dass Sie bei jedem Aufruf direkt auf die Datenbank gehen.
Standardmäßig bekomme ich sobald einmal aufgerufen wurde immer die bereits geladenen Objekte zurück.

Meine Konfiguration ist

Code:
   @ManyToMany(fetch = FetchType.LAZY, targetEntity = Kategorie.class, cascade = {CascadeType.MERGE, CascadeType.PERSIST })


gibt es etwas in die Richtung
Code:
loadAlwaysFromDB=true


Konnte nichts dazu finden.
Es handelt sich bei mir um einen Baum mit Kategorien, eine Kategorie kann beliebig viele Unterkategorien haben usw...

Danke Euch
Grüße aus München
Josef


Top
 Profile  
 
 Post subject: Re: LazyLoading reload über DB-Zugriff konfigurieren
PostPosted: Mon Feb 13, 2012 5:56 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Hallo Josef,

das was Du machen moechtest ist ziemlich ungewoehnlich, denn normalerweise versucht man immer die Datenbankzugriffe zu minimieren.
Wieso moechtest Du bei jedem Aufruf direkt auf die Datenbank gehen?
Gibt es da etwa jemand anderen (ausser Hibernate) der die Daten auf der Datenbank aendert?


Top
 Profile  
 
 Post subject: Re: LazyLoading reload über DB-Zugriff konfigurieren
PostPosted: Mon Feb 13, 2012 6:17 am 
Newbie

Joined: Mon Feb 13, 2012 4:43 am
Posts: 4
Hallo pb00067,

ja genau so ist es.
Ich nutze das ganze in einer Eclipse RCP Applikation.

Zum einen werden die Daten von
- anderen RCP Anwendern geändert,
- zum anderen von Cobol Jobs, welche ich aus der RCP heraus anstoße.

Deiner Frage nach befürchte ich, dass ich hier ein generelles Verständnisproblem habe?

Danke für dein promtes Post

Grüße
Josef


Top
 Profile  
 
 Post subject: Re: LazyLoading reload über DB-Zugriff konfigurieren
PostPosted: Mon Feb 13, 2012 8:49 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Hallo Josef,

der einfachste Weg, ist es dein Ausgangsobject zu 'refreshen' bevor Du erneut auf die Collection zugreifts,
damit wird beim Collection-Zugriff die Collection neu von der DB geladen:

Code:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("helloworld");
      EntityManager em = emf.createEntityManager();
      
      A a = new A();
      em.getTransaction().begin();
      em.persist(a);
      
      
      B b1 = new B();
      B b2 = new B();
      em.persist(b1);
      em.persist(b2);
      

      a.assB.add(b1);
      b1.assA=a;
      
      a.assB.add(b2);
                b2.assA=a;
      
      em.getTransaction().commit();
      em.clear();
                // ENDE VORBEREITUNG

      Session session = (Session) em.getDelegate();
      A person = (A) em.find(A.class, 1L);

//statement|select a0_.oid as oid1_0_ from A a0_ where a0_.oid=1
//resultset|select a0_.oid as oid1_0_ from A a0_ where a0_.oid=1|


      person.assB.isEmpty(); // Zugriff auf Collection

//statement|select assb0_.assA_oid as assA2_1_1_, assb0_.oid as oid1_, assb0_.oid as oid0_0_, assb0_.assA_oid as assA2_0_0_ from B assb0_ where assb0_.assA_oid=1
//resultset|assA2_0_0_ = 1, assA2_1_1_ = 1, oid0_0_ = 1, oid1_ = 1
//resultset|assA2_0_0_ = 1, assA2_1_1_ = 1, oid0_0_ = 2, oid1_ = 2
      
      em.refresh(person);

//statement|select a0_.oid as oid1_0_ from A a0_ where a0_.oid=1
//resultset|select a0_.oid as oid1_0_ from A a0_ where a0_.oid=1|


      person.assB.isEmpty(); // Erneuter zugriff auf die Collection
                                                (inzwischen hat extern jemand ein zu a assiziertes B mit oid=3 committed)

//statement|select assb0_.assA_oid as assA2_1_1_, assb0_.oid as oid1_, assb0_.oid as oid0_0_, assb0_.assA_oid as assA2_0_0_ from B assb0_ where assb0_.assA_oid=1
//resultset|assA2_0_0_ = 1, assA2_1_1_ = 1, oid0_0_ = 1, oid1_ = 1
//resultset|assA2_0_0_ = 1, assA2_1_1_ = 1, oid0_0_ = 2, oid1_ = 2
//resultset|assA2_0_0_ = 1, assA2_1_1_ = 1, oid0_0_ = 2, oid1_ = 3


Top
 Profile  
 
 Post subject: Re: LazyLoading reload über DB-Zugriff konfigurieren
PostPosted: Mon Feb 13, 2012 10:56 am 
Newbie

Joined: Mon Feb 13, 2012 4:43 am
Posts: 4
Hallo pb00067,

genau so hatte ich das Anfangs bzw. aktuell implementiert.

Das verhält sich bei mir dann bezüglich der neuen Assoziationen auch so wie bei Dir.
ABER:
Änderungen von primitiven Attributen in den bereits vorher geladenen B-Klassen bekomme ich so nicht, nur die neuen B-Assoziationen habe ich dann aktuell.

Die Attribute der bereits vorher vorhanden gewesenen B-Klassen bekomme ich nur, wenn ich bei A die Assoziation zu B wie folgt erweitere:
Code:
   @ManyToMany(fetch = FetchType.LAZY, targetEntity = B.class, cascade = {[color=#FF0000][b]CascadeType.REFRESH,[/b][/color] CascadeType.MERGE, CascadeType.PERSIST })


Und dann habe ich ein massives Performance Problem, weil er dann für jedes B, welches A zugeordnet ist einen Select auf die DB macht.

Ist das bei Dir auch so?

Einfach mal bei

Code:
(inzwischen hat extern jemand ein zu a assiziertes B mit oid=3 committed)

noch ein
Code:
update B where obj=2 set name="neuer Name"

machen.
Bin gespannt was er bei Dir dann macht.




Dankeschön für die Unterstützung pb00067
Grüße
Josef


Top
 Profile  
 
 Post subject: Re: LazyLoading reload über DB-Zugriff konfigurieren
PostPosted: Mon Feb 13, 2012 11:50 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Quote:
Änderungen von primitiven Attributen in den bereits vorher geladenen B-Klassen bekomme ich so nicht, nur die neuen B-Assoziationen habe ich dann aktuell.


Das ist so weil der Hibernate Persistent Context seinerseits ein "repeateable read" Isolation simuliert (und das ist gut so).
Zwar liefert die query B(obj=2) den Namen "neuer Name", da aber B(obj=2) schon vorher im "Persistent Context" geladen war,
werden deren Attribute nicht ueberschrieben.

Du muesstest also vor dem neu-lesen der Kollection zuerst alle alten B's aus dem Kontext mittels detach rauswerfen.

Code:
     for (B b : person.assB) {
             em.detach(b);
     }
     em.refresh(person);
     person.assB.isEmpty(); // Erneuter zugriff auf die Collection , auch die B's sollten nun die aktuellen Werte erhalten


Damit koenntest Du auf die krummen Cascade optionen verzichten und das Kollektion query sollte reichen die B's zu aktualisieren,
d.h. damit haettest Du nicht eine extra query pro assozierten B.


Top
 Profile  
 
 Post subject: Re: LazyLoading reload über DB-Zugriff konfigurieren
PostPosted: Mon Feb 13, 2012 4:03 pm 
Newbie

Joined: Mon Feb 13, 2012 4:43 am
Posts: 4
Hallo pb00067,

das hat mir sehr weitergeholfen!
Zusätzlich zum detach musste ich noch
bei
Code:
   @ManyToMany(fetch = FetchType.LAZY, targetEntity = B.class, cascade = {CascadeType.MERGE, CascadeType.PERSIST })


den CascadeType.PERSIST raus schmeißen, weil ich sonst bei refresh folgendes bekomme:

Code:
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: de.audi.sova.data.model.SourceAttribute
   at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:127)
   at org.hibernate.impl.SessionImpl.firePersistOnFlush(SessionImpl.java:834)
   at org.hibernate.impl.SessionImpl.persistOnFlush(SessionImpl.java:826)
   at org.hibernate.engine.CascadingAction$9.cascade(CascadingAction.java:357)
   at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
   at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
   at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
   at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:425)
   at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362)
   at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338)
   at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
   at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
   at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:154)
   at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145)
   at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
   at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:76)
   ... 50 more



Anscheinend wird ansonsten wohl bei .refresh() versucht, die "detached" Objekte zu speichern.
Aber lieber mache ich das .persist() nach unten manuell, anstatt nicht reloaden zu können.

pb00067, wie kann man deine/eure Leistungen honorieren? Ich finde es toll, das Ihr so schnell weiter helft!

Danke nochmals
Josef


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