I know this topic has been covered before, but I'd like to post my solution to the problem of serializing lazy persistent objects.
I wrote the following code to initialize a DeviceRepositoryObject, which is the base class for all of our persistent objects. It walks the graph and eagerly loads all objects as needed.
The initialized object can be sent to an RMI client, modified, and then sent back to the server to be saved via Hibernate. This works fine for us.
Code:
private void initialize(DeviceRepositoryObject dro) {
// We pass a Set to track which objects in the graph we have processed.
initialize(dro, new HashSet<DeviceRepositoryObject>());
}
private void initialize(DeviceRepositoryObject dro, Set<DeviceRepositoryObject> processed) {
if (processed.contains(dro)) {
return;
}
processed.add(dro);
if (dro.getClass().getName().indexOf("CGLIB") != -1) {
// For CGLIB objects, we get the implementation from the dbase
HibernateProxy hp = (HibernateProxy) dro;
LazyInitializer li = hp.getHibernateLazyInitializer();
// Use the implementation to walk the graph
dro = (DeviceRepositoryObject) li.getImplementation();
} else if (!Hibernate.isInitialized(dro)) {
Hibernate.initialize(dro);
}
// The persister has access to the child members of any DeviceRepositoryObject
EntityPersister persister = ((SessionImpl) m_session).getEntityPersister("", dro);
Object [] children = persister.getPropertyValues(dro, m_session.getEntityMode());
for (Object child : children) {
if (child != null) {
Class c = Hibernate.getClass(child);
if (DeviceRepositoryObject.class.isAssignableFrom(c)) {
// If its derived from DeviceRepositoryObject then recurse
initialize((DeviceRepositoryObject) child, processed);
} else if (child instanceof PersistentSet) {
// If its a Collection mapping then recurse over members
PersistentSet persistentSet = (PersistentSet) child;
if (!Hibernate.isInitialized(persistentSet)) {
Hibernate.initialize(persistentSet);
}
for (Object setMember : persistentSet) {
initialize((DeviceRepositoryObject) setMember, processed);
}
}
}
}
}
If you see something wrong with this code, please post your concerns. It seems to work for me.