Hi, Sebastian Götz wrote:
> Hi Jaime, > > > > after trying ym own solution I finally understand what you intended with > your approach. But let me post some code of how I am doing it: > > > > private XStream createXstreamInstance(final Class<?> p_clazz) > > { > > XStream xstream = new XStream() > > { > > @Override > > protected MapperWrapper wrapMapper(final MapperWrapper next) > > { > > return new HibernateMapper(next); > > } > > }; > > xstream.registerConverter(new HibernateProxyConverter()); > > xstream.registerConverter(new > HibernatePersistentCollectionConverter(xstream.getMapper())); > > xstream.registerConverter(new > HibernatePersistentMapConverter(xstream.getMapper())); > > xstream.registerConverter(new > HibernatePersistentSortedMapConverter(xstream.getMapper())); > > xstream.registerConverter(new > HibernatePersistentSortedSetConverter(xstream.getMapper())); > > // our own converter > > xstream.registerConverter(new > EntityExternalRefExportConverter(p_clazz)); > > > > return xstream; > > } > > > > class EntityExternalRefExportConverter implements Converter > > { > > private final Class<?> clazz; > > > > public EntityExternalRefExportConverter(final Class<?> p_class) > > { > > clazz = p_class; > > } > > > > @Override > > public void marshal(final Object p_object, final > HierarchicalStreamWriter p_writer, final MarshallingContext p_context) > > { > > p_writer.setValue(((BaseEntity) p_object).getId()); > > } > > > > @Override > > public Object unmarshal(final HierarchicalStreamReader p_reader, > final UnmarshallingContext p_context) > > { > > throw new Error("UnitExternalRefExportConverter should not be > used for unmarshalling. Use UnitExternalRefImportConverter instead"); > > } > > > > @Override > > public boolean canConvert(final Class p_clazz) > > { > > return BaseEntity.class.isAssignableFrom(p_clazz) && > !clazz.isAssignableFrom(p_clazz) && !p_clazz.isAssignableFrom(clazz); > > } > > } > > > > for (Class<?> clazz : entityClasses) > > { > > query = session.createCriteria(clazz); > > query.setProjection(Projections.rowCount()); > > > > count = (Number) query.uniqueResult(); > > > > // could by more efficient if we just changed the converters target > class via setter/getter > > // so we do not need to create a new xstream instance each time > > stream = createXstreamInstance(clazz); > > > > query = session.createCriteria(clazz); > > > > if (count != null) > > { > > // use batch fetching to reduce memory impact > > for (int i = 0; i < count.intValue(); i += batchSize) > > { > > query.setFirstResult(i); > > query.setMaxResults(batchSize); > > > > for (Object object : query.list()) > > { > > try > > { > > stream.toXML(object, zip); > > } > > catch (Exception e) > > { > > e.printStackTrace(); > > } > > } > > } > > } > > } > > > > > > As you can see my converter class tells that it can convert anything that > is a domain object (BaseEntity in my case) BUT NOT the currently exported > class. So if I export an employee for instance any references within the > employee class are converted just as serialized id but the employee itself > will be converter using the standard xstream way. > > By now this approach has one major mistake: If you have a domain object > that has references to objects of the same class (the supervisor in your > initial example for instance) then the whole objects will be serialized. I > have a hierarchical tree structure in the database this way which ends up > with a huge amount of data since each serialized object sucks in the > complete tree structure. Thats a bit of a pain for me and I think I > cannot solve it with this approach. But if one does not have such > references to the same object it works great. You might try to adjust your approach slightly by keeping track of the already converted objects: ============== %< ============== class EntityExternalRefExportConverter extends ReflectionConverter { public boolean canConvert(final Class p_clazz) { return BaseEntity.class.isAssignableFrom(p_clazz); } public void marshal(final Object p_object, final HierarchicalStreamWriter p_writer, final MarshallingContext p_context) { Set<Id> tracker = (Set<Id>)p_context.get("ID_TRACKER"); if (tracker == null) { p_context.put("ID_TRACKER", tracker = new HashSet<Id>()) } Id id = ((BaseEntity) p_object).getId(); if (tracker.add(id)) { super.marshal(p_object, p_writer, p_context); } else { p_writer.setValue(id); } } ============== %< ============== I think you get the idea. The code *assumes* that the object would normally be handled by the ReflectionConverter, but it might be the HibernateProxyConverter instead. You have to derive from the appropriate converter. Cheers, Jörg --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email