The entity structure is as follows:
Code:
@MappedSuperclass
public abstract class AbstractObject implements Serializable {
@EmbeddedId
private ObjectPrimaryKey objectPrimaryKey; // Composite key comprising two Strings and one BigDecimal
@Column(name = "createdTime", nullable = false)
private Date createdTime;
@Column(name = "expiryTime", nullable = false)
private Date expiryTime;
//Setters and Getters Ommitted for brevity
}
@Entity
public class MainObject extends AbstractObject implements Serializable {
//Various text fields ommited for brevity
@Embedded
private InnerObjectCollection innerObjectcollection;
}
@Embeddable
public class InnerObjectCollection implements Serializable {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<InnerObject> innerObjects;
}
@Entity
@Access(AccessType.FIELD)
public class InnerObject implements Serializable, Comparable<InnerObject>{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ob_id")
Long id;
@Transient
private AnotherObject object;
//Various string and date fields
private int ordinal;
public int compareTo(InnerObject innerObject) {
return ((Integer)this.ordinal).compareTo(innerObject.getOrdinal());
}
}
The error occurs in the following method call:
Code:
@Transactional(readOnly = true, propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
private Set<AbstractObject> getSomeObjects() {
Session session = this.getHibernateTemplate().getSessionFactory().getCurrentSession();
SQLQuery query = session.createSQLQuery(identityQuerySQL);
query.setParameter(...);
query.setParameter(...);
query.setResultTransformer(Transformers.aliasToBean(resultAlias));
return getObjectsForIdentities(session, query);
}
private Set<AbstractObjects> getObjectsForIdentities(Session session, SQLQuery query) {
List<ObjectPrimaryKey> primaryKeys = query.list();
Set<AbstractObjects> objects = new LinkedHashSet<AbstractObjects>();
for (ObjectPrimaryKey objectPrimaryKey : primaryKeys) {
AbstractObject obj = (AbstractObject) session.get(forClass, objectPrimaryKey); //forClass defined else where
objects.add(obj);
}
sortObjects(objects);
return objects;
}
private void sortObjects(Set<AbstractObjects> abstractObjects) {
for (AbstractObjects obj : abstractObjects) {
MainObject mObj = (MainObject) obj;
Collections.sort(mObj.getInnerObjectcollection().getInnerObjects());
}
}
Calling: Collections.sort(mObj.getInnerObjectcollection().getInnerObjects());
results in:
Code:
Caused by: org.hibernate.LazyInitializationException: illegal access to loading collection
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:363)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
at org.hibernate.collection.PersistentBag.toArray(PersistentBag.java:280)
at java.util.Collections.sort(Collections.java:154)
... 56 more
The error seems to be in trying to initialise InnerObjectCollection.innerObjects. This is set to FetchType.EAGER though so I don't understand why it would only be initialising when accessed. Surely it should already be loaded?
It's worth saying that the structure and querying above looks a little unauthodox and it is. There are good reasons for the way things are being done which aren't clear as I've greatly simplified the overall code structure.
Can anyone shed any light on why this is occurring? It's only on a small handful of transactions - a few times a week in 1000's of transactions.
The code is managed by an anotation based Spring transaction manager.