Question

I noticed that batch insert using MongoTemplate.insert(Collection<?> …) method is much slower than using MongoDB Java driver.

As far as I understand it, the differences comes from the fact that the MongoTemplate is performing some serial operations and I'm talking about the next lines of code :

for (T o : batchToSave) {

  initializeVersionProperty(o);
  BasicDBObject dbDoc = new BasicDBObject();

  maybeEmitEvent(new BeforeConvertEvent<T>(o));
  writer.write(o, dbDoc);

  maybeEmitEvent(new BeforeSaveEvent<T>(o, dbDoc));
  dbObjectList.add(dbDoc);
}

And :

for (T obj : batchToSave) {
  if (i < ids.size()) {
    populateIdIfNecessary(obj, ids.get(i));
    maybeEmitEvent(new AfterSaveEvent<T>(obj, dbObjectList.get(i)));
  }
  i++;
}

Now, is there a way to configure MongoTemplate to a void those heavy time consuming operations, maybe not publishing events or something?

Was it helpful?

Solution

So, first of all the question is: what do you get for the buck? You get:

  • optimistic locking
  • object-to-document mapping
  • persistence events
  • resource management
  • exception translation

So if you're asking whether it's possible to get all of this for free, the answer is clearly: no. But as usually it's the object to document conversion that takes the most time, there are a couple of options to tweak the process:

Implementing a custom Converter

Handing a complex domain object to the template will - by definition - require it to be translated into a DBObject. You can shortcut this by either implementing a Converter<YourType, DBObject> and register it (see the reference documentation for details). This will cause the reflection based conversion mechanism be skipped and your converter be invoked. This will allow you to still benefit from the optimistic locking and events.

Persisting a DBObject in the first place

An even more efficient way is just handing DBObjects to the template in the first place (i.e. do the conversion of the objects manually and outside the template). This will of course prevent the event and optimistic locking mechanism from being useful.

Use the callback methods

If you're really into skipping all of the mapping and eventing functionality, use the callback methods on MongoTemplate to interact with the driver API directly:

public void someMethod(final List<YourObject> objects) {

  template.execute("someCollection", new CollectionCallback<Void>() {
    public Void doInCollection(DBCollection collection) {
      // you code interacting with the collection
    }
  }
}

This will leave you with the last benefits of resource management and the exception translation of MongoDB exceptions into Spring's DataAccessException hierarchy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top