Hibernate: illegal access to loading collection

Kryptaesthesie

Erfahrenes Mitglied
Hallo,

ich habe ein kleines Problem mit meiner Webanwendung unter der Verwendung von Hibernate.

Ich habe den Fehler unten angefügt, da er länger ist.
Der Fehler tritt auf, wenn ich von Band das Set auf Concert aufrufe.

Mein Mapping von Band sieht so aus:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.giglocator.obj.db.Band" table="band">
		<id name="id" type="int" column="BAND_ID">
            <generator class="native"/>
        </id>
        
		<property unique="true" name="bandname"/>
		
		<property name="created" type="long"/>
		
		<many-to-one name="owner" class="com.giglocator.obj.db.User" fetch="select"/>
		
        <set name="contact" table="bandcontact" inverse="false">
        	<key>
                <column name="bandid" not-null="true" />
            </key>
			<one-to-many class="com.giglocator.obj.db.BandContact"/>
        </set>

	    <set name="concerts" inverse="false" lazy="false" table="attend" fetch="select">
	        <key>
                <column name="bandid" not-null="true" />
            </key>
	        <many-to-many entity-name="com.giglocator.obj.db.Concert">
	            <column name="concertID" not-null="true"/>
	        </many-to-many>
	    </set>
        
        <set name="adminUsers" inverse="false" lazy="true" table="band_acl" fetch="select">
        	<key>
                <column name="bandid" not-null="true" />
            </key>
            <many-to-many entity-name="com.giglocator.obj.db.User">
                <column name="userid" not-null="true" />
            </many-to-many>
        </set>
    </class>
</hibernate-mapping>

Von Concert so:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
	<class name="com.giglocator.obj.db.Concert" table="concert">
        <id name="id" type="int">
            <column name="concert_id" />
            <generator class="native"/>
        </id>
        
        <property name="comment" type="string">
            <column name="comment" />
        </property>
        
        <property name="created" type="long">
            <column name="created" />
        </property>
        
        <property name="dateTimeOfConcert" type="long">
            <column name="datetimeofconcert" />
        </property>
        
        <many-to-one name="location" class="com.giglocator.obj.db.Location" fetch="select">
            <column name="locationid" />
        </many-to-one>
        
        <set name="bands" inverse="true" lazy="true" table="attend" fetch="select">
            <key>
                <column name="concertid" not-null="true" />
            </key>
            <many-to-many entity-name="com.giglocator.obj.db.Band">
                <column name="bandid" not-null="true" />
            </many-to-many>
        </set>
    </class>
</hibernate-mapping>

Zum Testen verwende ich folgenden Code in einer JSP-Datei:
Code:
<%
	BandDAO bandDAO = new BandDAO();
	List<Band> artistlist = null;
	
	int max = 20;
	
	try {
		artistlist = bandDAO.getListOfBandsNewcomer(max);
	} catch(DAOException e) {
		logger.error("Fehler beim Holen der Newcomer.", e);
		artistlist = new ArrayList<Band>();
	}
	
	for(Band cur : artistlist) {
		Set<Concert> all = cur.getConcerts();
%>
	
		<span>Value: <%= cur.getBandname() %> :: <%= all.size() %></span><br />

<%
	}


	AbstractDAO.close();
%>

Und die Methode der DAO-Klasse sieht so aus:
Code:
	public List<Band> getListOfBandsNewcomer(int count) throws DAOException {
		try {
			begin();
			Criteria crit = getSession().createCriteria(Band.class);
			crit.addOrder(Order.desc("created"));
			crit.setMaxResults(count);
			List<Band> bands = crit.list();
			commit();
			return bands;
		} catch(HibernateException he) {
			rollback();
			String msg = "Die Bandliste konnte nicht abgerufen werden.";
			logger.error(msg, he);
			throw new DAOException(msg, he);
		}
	}

In den Pojo-Klasse habe ich kein Experimente - sprich sie sind schlicht und haben lediglich Get- u. Set-Methoden! :)

Also das lazy-Loading habe ich schon in jeder erdenklichen Form abgeändert. Das ändert an dem Fehler nichts!

Vielen Dank für eure Hilfe!
Gruß
Gerrit


Code:
11:31:58,374 ERROR LazyInitializationException:19 - illegal access to loading collection
org.hibernate.LazyInitializationException: illegal access to loading collection
	at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:341)
	at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
	at org.hibernate.collection.PersistentSet.hashCode(PersistentSet.java:355)
	at com.giglocator.obj.db.Band.hashCode(Band.java:94)
	at java.util.HashMap.put(HashMap.java:418)
	at java.util.HashSet.add(HashSet.java:194)
	at java.util.AbstractCollection.addAll(AbstractCollection.java:318)
	at org.hibernate.collection.PersistentSet.endRead(PersistentSet.java:273)
	at org.hibernate.engine.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:183)
	at org.hibernate.engine.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:268)
	at org.hibernate.engine.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:249)
	at org.hibernate.loader.Loader.endCollectionLoad(Loader.java:866)
	at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:853)
	at org.hibernate.loader.Loader.doQuery(Loader.java:717)
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:223)
	at org.hibernate.loader.Loader.loadCollection(Loader.java:1916)
	at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:71)
	at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:520)
	at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
	at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1593)
	at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:344)
	at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
	at org.hibernate.collection.PersistentSet.hashCode(PersistentSet.java:355)
	at com.giglocator.obj.db.Concert.hashCode(Concert.java:93)
	at java.util.HashMap.put(HashMap.java:418)
	at java.util.HashSet.add(HashSet.java:194)
	at java.util.AbstractCollection.addAll(AbstractCollection.java:318)
	at org.hibernate.collection.PersistentSet.endRead(PersistentSet.java:273)
	at org.hibernate.engine.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:183)
	at org.hibernate.engine.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:268)
	at org.hibernate.engine.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:249)
	at org.hibernate.loader.Loader.endCollectionLoad(Loader.java:866)
	at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:853)
	at org.hibernate.loader.Loader.doQuery(Loader.java:717)
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:223)
	at org.hibernate.loader.Loader.loadCollection(Loader.java:1916)
	at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:71)
	at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:520)
	at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
	at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1593)
	at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:454)
	at org.hibernate.engine.StatefulPersistenceContext.initializeNonLazyCollections(StatefulPersistenceContext.java:791)
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:228)
	at org.hibernate.loader.Loader.doList(Loader.java:2147)
	at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2026)
	at org.hibernate.loader.Loader.list(Loader.java:2021)
	at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:94)
	at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1483)
	at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:298)
	at com.giglocator.obj.db.dao.BandDAO.getListOfBandsNewcomer(BandDAO.java:83)
	at org.apache.jsp.try_jsp._jspService(try_jsp.java:133)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:337)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
 
Zuletzt bearbeitet:
Hi Kryptathesis,

bisher habe ich noch nicht viel mit Hibernate und Mapping-Dateien gemacht (bisher nur Annotationen) und bisher habe ich auch immer NamedQueries verwendet, weshalb ich nicht weiß, ob ich richtig liege.

Ich habe mal gegoogled und an der Stelle, wo du

Code:
List<Band> bands = crit.list();

habe ich bisher immer nur

Code:
List bands = crit.list();

gefunden. Kann es sein, dass das daran liegt? Würde ja auch zu einer "illegal access to loading collection"-Meldung passen?!

Ist aber nur eine Vermutung/ein Versuch. Ansonsten würde ich es einfach mal debuggen um zu schauen, an welcher Stelle es genau hängt und mich dann auf die Stelle einschießen und googlen...

Viele Grüße,

Dirk
 
So ein Fehler tritt auf wenn eine Collection layz (also beim ersten Zugriff und nicht direkt beim Abrufen) initialisiert wird und keine Session mehr vorhanden ist. Google spuckt dazu haufenweise Ergebnisse aus, schau doch mal ob du da was findest was dir bei deinem Problem hilft.
 
Hallo zusammen

Code:
List<Band> bands = crit.list();

habe ich bisher immer nur

Code:
List bands = crit.list();

gefunden. Kann es sein, dass das daran liegt? Würde ja auch zu einer "illegal access to loading collection"-Meldung passen?!
Das war leider nicht des Rätsels Lösung! :(


So ein Fehler tritt auf wenn eine Collection layz (also beim ersten Zugriff und nicht direkt beim Abrufen) initialisiert wird und keine Session mehr vorhanden ist. Google spuckt dazu haufenweise Ergebnisse aus, schau doch mal ob du da was findest was dir bei deinem Problem hilft.
Ja, das habe ich beim Googeln auch schon herausgefunden.
Aber ich habe concerts bereits auf lazy=false gestellt und trotzdem kommt der Fehler. Ich wüsste einfach nicht wo die Session verschwunden geht?!

Also der Fehler tritt wirklich erst auf, sobald die Konzerte geladen benötigt werden!
Außerdem auch nur dann, wenn band.getConcerts().size() > 0 ist!!

Danke trotzdem schon mal für eure Hilfe!
 
Hallo :)
Ich konnte das Problem noch ein wenig weiter einkreisen.

Im folgenden Mapping von Concert ist eine Referenz auf Location.
Von Concert so:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
	<class name="com.giglocator.obj.db.Concert" table="concert">
        <id name="id" type="int">
            <column name="concert_id" />
            <generator class="native"/>
        </id>
        
        <property name="comment" type="string">
            <column name="comment" />
        </property>
        
        <property name="created" type="long">
            <column name="created" />
        </property>
        
        <property name="dateTimeOfConcert" type="long">
            <column name="datetimeofconcert" />
        </property>
        
        <many-to-one name="location" class="com.giglocator.obj.db.Location" fetch="select">
            <column name="locationid" />
        </many-to-one>
        
        <set name="bands" inverse="true" lazy="true" table="attend" fetch="select">
            <key>
                <column name="concertid" not-null="true" />
            </key>
            <many-to-many entity-name="com.giglocator.obj.db.Band">
                <column name="bandid" not-null="true" />
            </many-to-many>
        </set>
    </class>
</hibernate-mapping>

Das Mapping von Location sieht so aus:
Code:
<hibernate-mapping>
	<class name="com.giglocator.obj.db.Location" table="LOCATION">
        <id name="id" column="LOCATION_ID">
            <generator class="native"/>
        </id>
        <property name="city" type="string"/>
        <property name="comment" type="string"/>
        <property name="created" type="long"/>
        <property name="email" type="string"/>
        <property name="fax" type="string"/>
        <property name="name" type="string"/>
        <property name="phone" type="string"/>
        <property name="street" type="string"/>
        <property name="zipcode" type="string"/>
        
		<many-to-one name="bandOfReference" class="com.giglocator.obj.db.Band" fetch="select">
            <column name="idofreference" />
        </many-to-one>
        <set name="concerts" inverse="true" lazy="true" table="concert" fetch="select">
            <key>
                <column name="locationid" />
            </key>
            <one-to-many class="com.giglocator.obj.db.Concert" />
        </set>
    </class>
</hibernate-mapping>

Könnte es sein, dass die Referenz zurück auf Band und das Set zu Concert ein Problem darstellen? Weil ich hätte einen Kreislauf! Oder merkt Hibernate das irgendwie, dass sich das Laden der Objekte im Kreis dreht?

Danke für eure Hilfe!
Gruß
Gerrit
 
Zurück