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