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. That’s 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


Reply via email to