Frage

UPDATE:BEISPIEL ZUR VERDEUTLICHUNG Ich werde ein Beispiel dafür, was passiert, nur um die situation zu klären in meinem Spring + Hibernate-Anwendung.Vorstellen, ich habe diese zwei Entitäten (angenommen, Getter und setter existiert auch)

@Entity
public class Class1(){
  private Integer id;

  @OneToOne
  private Class2 object2;
}

@Entity
public class Class2(){
  private Integer id;

  @OneToOne
  private Class1 object2;
}

Also in meiner Datenbank habe ich zwei Tabellen anzeigen jede Instanz jedes Objekts.Angenommen, ich habe in der Datenbank gespeichert, diese Objekte:

  • objectA (Klasse Class1) :id = 1 , object2 = objectB
  • objectB (Klasse Class2) :id = 2 , object2 = objectA
  • objectC (Klasse Class2) :id = 3 , object2 = null was bedeutet Ein anb B verknüpft sind.Angenommen, ich will jetzt link objectA zu objectC.Es bedeutet, ich muss auf den link löschen in der objectB zu.

Dies zu tun, die ich tun die folgenden:

//I get the objectA from database
Class1 storedObjectA = myservice.find(objectAId);
//Now in storedObject1 I have the same as what it is stored as objectA

//I change only the object2 attribute of it
storedObject1.setObject2(objectC);

//I search again in the database to see objectA
Class1 reStoredObjectA = myservice.find(objectAId);

restoredObjectA ist jetzt:

  • restoredObjectA (class = "Class1") id = 1, object2 = objectC

obwohl in der Datenbank vorhanden ist:

  • restoredObjectA (class = "Class1") id = 1, object2 = objectB

Die Methode find hat nicht gesucht werden in der Datenbank und ich habe die Vorherige Suche wenn ich meine Abfrage-und second-level-caches deaktiviert.Die Methode finden, geht nur an das DAO wo es führt auf den entityManager.finden Class1.class, id) Wie kann ich eine zweite finden, suchen in der Datenbank?

Vielen Dank


(Vollständige Erklärung)

Hallo,

Ich habe eine Anwendung, die Spring 3 und Hibernate.Ich habe eine Entität mit dem Namen Class1, die in einer Datenbank gespeichert ist.Diese Entität hat eine OneToOne-link zu einer anderen Entität namens Class2.Class2 hat einen anderen OneToOne Link zu Class1, und beide verbindungen haben eine einzigartige Eigenschaft auf true gesetzt ist.

Ich habe den folgenden code in meinem controller:

//I have an object called dataFromUser which is instance of Class1 and
// it is obtained via @ModelAttribute annotation from a form

Integer id = dataFromUser.getId();

//I get correctly the stored object from the database
Class1 storedData = myService.find(id); //this will call em.find of hibernate

//I set to the stored data the attribute I want to change
storedData.setObject2();

//I save again the object
myService.save(storedData);

Die Methode speichern in myService wird die entity-manager zur Speicherung der Daten, aber vor, dass Sie überprüfen Sie die vorherigen Assoziation zwischen Objekt Class1 und Class2 Objekt zu löschen, im Falle eines neuen Objekts Class2 gesetzt hat, um die Instanz von Class1.Aus diesem Grund habe ich zu nennen find-Methode wieder, um zu sehen, was ist in meiner Datenbank

In der Service:

@Transactional
public void save(Class1 object1){
   Class1 objectFromDB =  myDAO.find(object1.getId());
   // ....  update the old object and save
}

Das problem ist, dass objectFromDB in den Dienst ist nicht das gleiche wie wenn ich myService.finden(id) in die Steuerung.Das problem ist, dass es nicht suchen, für die es in der Datenbank, aber es ist die Suche in Speicher.Ich weiß es, weil es keine SQL-Anweisung protokolliert, wenn der zweite find () - Methode aufgerufen wird.Als ich das getan hatte, setObject2() auf der storedData Objekt bekomme ich genau dieses Objekt, wenn ich rufe find-Methode für die zweite Zeit, und die Datenbank nicht enthalten, weil es noch nicht gespeichert worden ist, noch.

Ich habe versucht, disable Cache in meiner Konfiguration nur um es zu versuchen, aber es ist immer noch geschieht.Ich habe eine ehCache mit dieser Konfiguration:

In persistence.xml ich habe diese Eigenschaften (ich habe auf false gesetzt beiden caches):

    <properties>
     <!-- Hibernate 3.5.0 - try org.hibernate.cache.* package -->
  <property name="hibernate.cache.provider_class"
               value="net.sf.ehcache.hibernate.SingletonEhCacheProvider" />
   <property name="hibernate.cache.use_query_cache" value="false" />
  <property name="hibernate.cache.use_second_level_cache" value="false" />
  <property name="hibernate.generate_statistics" value="true" />
  <property name="hibernate.cache.use_structured_entries" value="false" />
  <property name="hibernate.format_sql" value="true" />
  <!-- http://www.jroller.com/eyallupu/entry/hibernate_s_hbm2ddl_tool -->
  <!-- create, create-drop, update, validate -->
  <property name="hibernate.hbm2ddl.auto" value="update" />
    </properties>  

In meinem ehcache.xml ich habe auf 0 gesetzt maxElementsInMemory und overflowToDisk auf false zum deaktivieren es auch.

Gibt es eine Möglichkeit, diese situation zu vermeiden?

Vielen Dank.

War es hilfreich?

Lösung 2

OK, ich finde es heraus.Das problem ist, dass hibernate sieht für die Objekte in seiner Sitzung vor der Suche in der Datenbank.ich musste also detached das Objekt in der Sitzung, bevor Sie es ändern.Zu tun in den Ruhezustand:

    //being em my EntityManager instance
    Session session = (Session) em.getDelegate();
    session.evict(plan); 
    //Now the find object will not get the object wich is in session 
    //but the one in database

Andere Tipps

Ich bin nicht sicher, ob ich das richtig verstanden habe, aber nur für den Fall ...


Es gibt zwei Methoden, um ein Objekt geladen.Es gibt einen Unterschied, wenn das Objekt nicht im aktuellen Speicher Kontext:

  • Man geht sicher auf die Datenbank, gibt die Instanz, wenn es vorhanden ist, oder null sonst.
  • Die andere erstellt lediglich einen Proxy mit der richtigen id, die ohne Umweg sofort in die Datenbank, und Bearbeiten Sie es bei späteren Operationen (evtl. beim Spülen).

Sie scheinen sich mit dem zweiten ein, vielleicht könnten Sie versuchen, den ersten und sehen, ob es Ihr problem löst?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top