DAO -> Exception

Status
Nicht offen für weitere Antworten.

MQue

Top Contributor
Hallo,

ich hab ein Problem mit einer Hibernate- Session, ich habe in meiner DAO- Klasse 2 Methoden, welche ich unten aufgelistet habe (getSet und find).
Die Methode getSet wird aufgerufen um von einer Person alle Events zu erhalten,
wenn ich das finally wie unten auskommentiere, dann funktionierts auch nur wenn ich das finally nicht auskommentiert habe, dann bekomme ich die Fehlermeldung:

Code:
failed to lazily initialize a collection of role: ... no session or session was closed

was kann ich da machen bzw. wie macht man das normal? Ich schätze mal das ist ja was, das fast jeder benötigt bei einer m:n oder 1:m Verbindung.

Vielen Dank für Hilfe,
lg



Java:
public Set getSet(Class clazz, Long id) {
        final Person person = (Person) find(clazz, id);
        Set set = new HashSet();
        set.addAll(person.getEventlList());
        return set;
        }

Java:
protected Object find(final Class clazz, final Long id) {
        Object obj = null;
        try {
            startOperation();
            obj = session.load(clazz, id);
            tx.commit();
            }
        catch (HibernateException e) {
            handleException(e);
            }
       /* finally {
            HibernateFactory.close(session);
            }*/
        return obj;
        }
 
S

SlaterB

Gast
drei Möglichkeiten:
1. die Session solange offen halten, wie das Objekt verwendet wird, also SessionManagement außerhalb des Daos
(in Web-Anwendungen z.B. OpenSessionInView)

eine neue Session für jede einzelne Query klingt selbst bei einem Session-Pool unnötig aufwendig

2. kein Lazy-Loading

3. im Dao alle benötigten Daten initialisieren, z.B. durch Aufruf von getEventlList(),
was aufzurufen ist könnte ein Parameter steuern
 

MQue

Top Contributor
drei Möglichkeiten:
1. die Session solange offen halten, wie das Objekt verwendet wird, also SessionManagement außerhalb des Daos
(in Web-Anwendungen z.B. OpenSessionInView)

Das ist eh das, was ich jetzt mache mit dem auskommentieren von finally, dann ist die session halt immer offen da ich in meinem Programm immer wieder die Liste benötige, was wahrscheinlich auch wieder nicht so gut ist, oder?
 
M

maki

Gast
Willkommen bei den LazyInitExceptions, willkommen bei Hibernate.. *g*

Frage, wozu braucht man eine Transaktion bei einem find und wozu sollte man sie dort committen?
Mit hardcodiertem Transactionhandling verbaust du dir ganz schell ein sinnvolles & flexibles Transactionhandling.

Die Session solange offenhalten wie sinnvoll/nötig, für immer ist sicherlich nicht was du möchtest.

Irgendwie sieht dein find sehr allgemein aus, war das absicht?
 

MQue

Top Contributor
Frage, wozu braucht man eine Transaktion bei einem find und wozu sollte man sie dort committen?
Mit hardcodiertem Transactionhandling verbaust du dir ganz schell ein sinnvolles & flexibles Transactionhandling.
Irgendwie sieht dein find sehr allgemein aus, war das absicht?

Das hab ich mir abgeschaut und weiß momentan nicht viel besser wie ich es machen könnte. Das ist meine Quelle: Generic Dao: Find : DAO Generic DAOHibernateJava
Wäre Dankbar für einen Tipp!.
V.D.
lg
 
Zuletzt bearbeitet:

byte

Top Contributor
Zwei Dinge:
1. Um sicherzustellen, dass die Daten auch wirklich geladen werden (und nicht bloß ein Proxy erzeugt wird), solltest Du Session#get() statt load() benutzen!
2. Wenn die Entität Assoziationen zu anderen Entitäten enthält und Du diese direkt mitladen willst, dann solltest Du Fetch Joins benutzen beim Laden des Objekts! Wenn Du das machst, kannst Du auch ohne offene Session auf diese Objekte zugreifen.
 

MQue

Top Contributor
Hallo,

ok, das erste hab ich, ich hab load durch get in der Methode find ersetzt, mit dem 2. komme ich nicht klar, diese Fetch Joins muss ich ja auch irgendwie in die Methode find einbauen, oder ?

Java:
protected Object find(final Class clazz, final Long id) {
        Object obj = null;
        try {
            startOperation();
            obj = session.get(clazz, id);
            tx.commit();
            }
        catch (HibernateException e) {
            handleException(e);
            }
        finally {
            //HibernateFactory.close(session);
            }
        return obj;
        }


Danke für die Hilfe,
lg
 

byte

Top Contributor
Ich würde das Get einfach durch HQL ersetzen:

[HQL]select distinct a
from A a
left join fetch a.b[/HQL]

Du könntest auch alternativ im Mapping das Fetching der Assoziation auf EAGER setzen. Dann holt er die Objekte auch bei Session#get() direkt mit rein. Allerdings werden diese Mappings ignoriert, sobald Du ein spezifisches Query / Criteria baust.
 

MQue

Top Contributor
Ich würde das Get einfach durch HQL ersetzen:

[HQL]select distinct a
from A a
left join fetch a.b[/HQL]

Du könntest auch alternativ im Mapping das Fetching der Assoziation auf EAGER setzen. Dann holt er die Objekte auch bei Session#get() direkt mit rein. Allerdings werden diese Mappings ignoriert, sobald Du ein spezifisches Query / Criteria baust.

Tut mir leid, wenn ich so viel nachfrage, aber ich hab momentan keine Tau, wie ich das machen kann, muss ich dieses HQL in die Methode "find()" schreiben oder wie mach ich das, könntest du mir vielleicht schreiben, wie man das jetzt mit JAva- Code macht?
lg
 

byte

Top Contributor
So ungefähr:

Java:
Query query = session.createQuery("select distinct a from A a left join fetch a.b where a.id = :id");
query.setLong("id", id);
A a = (A)query.uniqueResult();

A ist die gemappte Hibernate Klasse und a.b ist die Assoziation in der Klasse A. Ich bin mal davon ausgegangen, dass die ID vom Typ Long ist.
 

MQue

Top Contributor
So ungefähr:

Java:
Query query = session.createQuery("select distinct a from A a left join fetch a.b where a.id = :id");
query.setLong("id", id);
A a = (A)query.uniqueResult();

A ist die gemappte Hibernate Klasse und a.b ist die Assoziation in der Klasse A. Ich bin mal davon ausgegangen, dass die ID vom Typ Long ist.

jetzt hab ich das Problem, dass ich eine m:n Verbindung habe und so weit ich das einsehen kann, sich die Abfrage auf eine 1:n- Abfrage bezieht,
Außerdem habe ich keine Ahnung, was a.b ist, Was ich versteh ist das:

SQL:
* für alle Spalten
SELECT DISTINCT * FROM tabelle1 AS t1 LEFT JOIN FETCH a.b? WHERE t1.id = :id;
 

byte

Top Contributor
Falsch. Es ist im HQL völlig egal, ob Du in der DB eine 1:n oder eine n:m Beziehung hast. HQL bezieht sich auf das Objektmodell und nicht auf das DB-Schema! Das ist der größte Unterschied zu SQL!

Am besten liest Du Dir erstmal die Grundlagen zu Hibernate und HQL durch. Es wäre zu mühselig hier jede Kleinigkeit zu erläutern. Ich kann Dir gerne Input geben, aber nachschlagen musst Du schon alleine.
 

MQue

Top Contributor
ok, danke, hab ich gemacht,
weiteres problem bei meinen n:m Verbindungen, wenn ich einen Eintrag aus einer Tabelle löschen möchte, bekomme ich

Java:
org.hibernate.exception.ConstraintViolationException: could not delete: [net.jank.ppos.database.pool.Connections#32768]
        at net.jank.ppos.database.dao.AbstractDao.handleException(AbstractDao.java:81)

Was kann ich da machen bzw. was muss ich da bei cascade= hinschreiben, wenn das letzte Objekt gelöscht werden soll, soll dieses gelöscht werden unabhängig von den Relationen,
 

byte

Top Contributor
Du musst schon mit mehr Informationen rausrücken, sonst kann man nur mutmaßen.

Ist es eine bidirektionale Verbindung? Hast Du die Referenzen in allen Objekten vor dem Speichern korrekt entfernt?
 

MQue

Top Contributor
Hallo, so schaut es momentan aus, das interessante ist, dass, wenn ich in beiden hbm.xml unter set inverse="true" hinschreibe, keine Exception mehr bekomme aber in der Zwischentabelle Person_Event nichts mehr eingetragen wird,
Bitte um Hilfe,
lg


Code:
// in Event.hbm.xml
<set inverse="true" name="participants" table="Person_Event">
      <key column="Event_ID"/>
      <many-to-many class="de.dummy.Person" column="Person_ID"/>
</set>

// in Person.hbm.xml
<set name="PersonList" table="Person_Event">
      <key column="Person_ID"/>
      <many-to-many class="de.dummy.Event" column="Event_ID"/>
</set>

auch wenn ich das set- Element in Event.hbm.xml rausgebe, ändert sich nichts

Code:
 public void removeEvent(final Event event, final Person person) {
        person.getPersonList().remove(event);
        event.getEventList().remove(person);
        eventDao.delete(event);
        }

Code:
protected void delete(final Object obj) {
        try {
            startOperation();
            session.delete(obj);
            tx.commit();
            }
        catch (HibernateException e) {
            handleException(e);
            }
        finally {
            HibernateFactory.close(session);
            }
        }
 
Zuletzt bearbeitet:

MQue

Top Contributor
Du musst DELETE kaskadieren, sonst wirds nicht funktionieren.

ich hab bei beiden schon (cascade="all") und auch cascade="delete" hingeschrieben, ohne wirkung, die hbm Dateien werden aber verwendet, wenn ich was falsches hinschriebe, meckert er

[XML]
<set inverse="true" name="participants" table="Person_Event" cascade="all">
<key column="Event_ID"/>
<many-to-many class="de.dummy.Person" column="Person_ID"/>
</set>

[/XML]
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen


Oben