Hallo,
ich habe ein Problem in meiner Web Anwendung mit Hibernate 3.0. Nach dem Speichern eines neuen Objektes und dem anschließenden Aufrufen werden teilweise falsche Referenzen angezeigt.
Ich beschreibe erst einmal beispielhaft die Objektherachie:
"Hersteller"
- Id
- Name
- Ort
-...
"Arbeitsgang"
- Id
- Name
- ...
"Fenster"
- Id
- Name
- Größe
- Arbeitsgang (Referenz zum Objekt Arbeitsgang)
- Hersteller (Referenz zum Objekt Hersteller)
- ...
Auszugsweise die hbm.xml Dateien dazu:
Fenster:Code:
<id name="id" column="ID" type="java.lang.Long" unsaved-value="null">
<generator class="identity">
</generator>
</id>
<many-to-one class="com.test.Arbeitsgang" fetch="select"
insert="false" lazy="false" name="arbeitsgang" update="false">
<column name="arbeitsgangId" scale="0"/>
</many-to-one>
<property generated="never" lazy="false" name="arbeitsgangId" type="java.lang.Long">
<column name="arbeitsgangId" not-null="false" scale="0"/>
</property>
<many-to-one class="com.test.Hersteller" fetch="select"
insert="false" lazy="false" name="hersteller" update="false">
<column name="herstellerId" scale="0"/>
</many-to-one>
....
Arbeitsgang:Code:
<id name="id" column="ID" type="java.lang.Long" unsaved-value="null">
<generator class="identity">
</generator>
</id>
... (restlichen Entitäten sind uninteressant)
Hersteller:Code:
<id name="id" column="ID" type="java.lang.Long" unsaved-value="null">
<generator class="identity">
</generator>
</id>
... (restlichen Entitäten sind uninteressant)
Ich erstelle ein neues Fensterobjekt und weise dem ein bestehendes Hersteller- und Arbeitsgangobjekt zu. Anschließend speichere ich das Fensterobjekt:
Code:
Session session = openSession(); // Funktion um eine Session über eine SessionFactory zu erstellen / öffnen
try {
beginTransaction(session);
session.save(transientInstance);
commit();
log.debug("save successful");
} catch (RuntimeException re) {
log.error("get failed", re);
throw re;
}finally {
closeSession();
}
Als nächstes hole ich mir direkt die Fensterobjekte anhand eines Arbeitsganges (Id):
Code:
Session session = openSession();
try {
beginTransaction(session);
Fenster instance = null;
String sql = "from Fenster as f LEFT OUTER JOIN f.hersteller LEFT OUTER JOIN f.arbeitsgang WHERE f.arbeitsgangId="+id;
Query query = session.createQuery(sql);
Iterator it = query.list().iterator();
while(it.hasNext()){
Object[] o = (Object[]) it.next();
Fenster fenster = (Fenster) o[0];
instance = fenster;
}
commit();
return instance;
} catch (RuntimeException re) {
log.error("get failed", re);
throw re;
}finally {
closeSession();
}
Und jetzt zu dem Problem. In der Datenbank werden die Objekte richtig gespeichert; jeder Fensterdatensatz referenziert richtig auf den Hersteller und auch auf dem Arbeitsgang. Wenn ich mir die Datensätze in meiner Webanwendung mit der zuvor beschrieben Methode anzeigen lassen (auch im Debug Modus), sehe ich dass manche Fensterobjekte einen Arbeitsgang an Board haben, und manche nicht. Stoppe ich den Tomcat und starte ihn wieder, werden mir die Referenzen richtig angezeigt. Mir kommt es so vor als hätte ich ein Caching Problem. Wo dran könnte das liegen?
Noch eine Kleinigkeit. Die Fensterklasse hat jeweils die Arbeitsgang- und die Herstellerklasse an Board. Auch wenn die Referenzen falsch sind, könnte ich durch das Iterieren in der Liste auf die anderen Objekte zugreifen:
Code:
while(it.hasNext()){
Object[] o = (Object[]) it.next();
Fenster fenster = (Fenster) o[0];
Hersteller hersteller = (Hersteller) o[1]; // Dieses Objekt wurde richtig zugewiesen
Arbeitsgang arbeitsgang = (Arbeitsgang) o[2]; // Auch dieses Objekt wurde richtig zugewiesen
instance = fenster;
}
Aber ich möchte ja nicht immer über die gesamte Liste iterieren um an die richtigen Objekte zu kommen, dass müßte auch ohne klappen, oder?
Hoffentlich versteht man mein Problem.
Vielen Dank für Eure Hilfe.
Daniel