-->
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.  [ 3 posts ] 
Author Message
 Post subject: Dirty Flag auf Attribut-Ebene
PostPosted: Mon Apr 06, 2009 7:23 am 
Newbie

Joined: Mon Apr 06, 2009 6:43 am
Posts: 2
Hibernate version: 3.2.3.ga

Tach zusammen,

wir setzen Hibernate gemeinsam mit EJB 2 SessionBeans mehr oder weniger erfolgreich ein. Solange wir uns nur innerhalb einer Session bewegen funktioniert alles tadellos.

Nun habe ich folgendes Problem (unten gibt's Code-Snippets):

1. ich erzeuge ein POJO A
2. A erhält ein assoziiertes Objekt B (persistent, per Query gefunden, ohne nachgeladene Assoziation C)
3. remote übertragen und per Session#save speichern

Resultat: Es wird die Assoziation B zu C gelöscht. Klar, weil in dem Attribut B#c null steht.

Nun die Idee: Kann ich Hibernate irgendwie sagen, dass es bei einem Session#save oder Session#merge bestimmte Attribute nur updaten soll, wenn diese als "dirty" markiert sind? bspw. über B#isCDirty. Ggf. könnte ich auch eine Art Interceptor einbauen. Nur habe ich bei dem Interceptor keine Idee, wie ich Hibernate sagen kann "und das Attribute jetzt nicht speichern"...

Hoffentlich geht's...

sMArtin

Testcode:
Code:
A a = new A();
a.setName("Herbert");

// dieses B hat kein geladenes C, obwohl es in der DB ein C gibt
B b = myRemoteService.findB();
a.setB(b);

myRemoteService.createA(a);

A actual = myRemoteService.findA();

assertNotNull(actual); // ist ok
assertNotNull(actual.getB()); // ist ok
assertNotNull(actual.getB().getC()); // schlägt fehl!


A.java
Code:
public class A {
  private String name;
  private B b;
  private boolean isBDirty = false;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getB() {
    return b;
  }

  public void setB(String b) {
    this.b = b;
    this.isBDirty = true;
  }

  public boolean isBDirty() {
    return this.isBDirty;
  }
}


B.java
Code:
public class B {
  private String name;
  private C c;
  private boolean isCDirty = false;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getC() {
    return c;
  }

  public void setC(String c) {
    this.c = c;
    this.isCDirty = true;
  }

  public boolean isCDirty() {
    return this.isCDirty;
  }
}


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 06, 2009 9:54 am 
Expert
Expert

Joined: Thu Jan 08, 2009 6:16 am
Posts: 661
Location: Germany
Ich gehe davon aus, dass C in B lazy geladen wird, und du deswegen sagst, B "hat kein geladenes C".
Wenn es so ist, dann ersetzt Hibernate das Objekt durch einen Proxy, bis das erste mal drauf zugegriffen wird. Beim Speichern funktioniert dann auhc alles.

So wie du dein Problem schilderst, scheinst du aber selber noch mal die Entity B in ein eigenes B zu mappen, sodass an Cs stelle nur null steht. Daher löscht Hibernate es wohl beim Speichern. Ist das korrekt? (und wars verständlich??)

_________________
-----------------
Need advanced help? http://www.viada.eu


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 09, 2009 2:19 am 
Newbie

Joined: Mon Apr 06, 2009 6:43 am
Posts: 2
Hi,

sorry für die späte Antwort. Ein Kollege hat sich des Themas angenommen und ich musste mich erstmal auf den aktuellen Stand bringen lassen.

Quote:
So wie du dein Problem schilderst, scheinst du aber selber noch mal die Entity B in ein eigenes B zu mappen, sodass an Cs stelle nur null steht. Daher löscht Hibernate es wohl beim Speichern. Ist das korrekt? (und wars verständlich??)


Prinzipiell ist das richtig, allerdings nicht ganz. Wir setzen - wie oben beschrieben - EJB2 ein. Sobald ich Remote-Zugriffe auf meinen Application-Layer mache, müssen die Objekte serialisiert werden. Daher werden sie von der Hibernate-Session getrennt. Also haben wir eine Klasse, die die Hibernate-Proxies wegschmeißt und null setzt, da es sonst bei jedem Zugriff auf der Remote-Seite zu einer LazyInitialisationException kommt.
Wir können aber auch nicht den gesamten Objektbaum nachladen, da dieser ggf. extrem groß (sher viele Objekte oder große Objekte wie Files) werden kann und z.B. der Presentation-Layer i.d.R. nur Zugriff auf einen Ausschnitt des Objekt-Baums benötigt.

Inzwischen sind wir bei "collection-type" angekommen. Wir überschreiben den Standard CollectionType und ändern das Verhalten beim Persistieren. Es wird ein eigenes Set geben, welches sich die Änderungen an sich selbst merkt. Diese Änderungen werden durch den CollectionType ausgewertet und mit dem Stand in der DB gemerged.

Für zu-1-Beziehungen werden wir Persister schreiben, die die Funktionalität vom OneToOnePersister und ManyToOnepersister erweitern. Sie werten eine isDirty-Map in den Pojos aus und entscheiden so, ob die Assoziation aktualisiert werden muss oder nicht.

Viele Grüße, sMArtin


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