Spring Data and MongoDB: A Mismatch Made In Hell
The Spring guys love to tout their support for MongoDb as an advantage over frameworks like JEE. However, using it in a real life project shows how severely lacking and fundamentally mis-designed the framework is.
Spring Data MongoDB tries to shoehorn an ORM style strictness to a fundamentally non-relational database, resulting in it being rendered useless in real life. Here are some reasons why:
1. Cant retrieve fields - Full document only
This is the biggest indicator of how flawed Spring Mongo’s design is. It tries to model documents like rows in a SQL database and wants you to make ‘entity’ classes like an ORM. Guess what, the two are not the same. A document can be far more complex and larger than a typical row in sql database.
With a row in a sql db, it is assumed that you will pull out all of it on most queries, otherwise the data is usually split in multiple tables.
But documents are a different beast. Documents are nested within each other, and most of the time you only want to pull out a small subset of it from your database.
But with Spring Mongo’s ‘entity’ modeling, you are forced to pull out your entire document on each query.
2. No DBRef lazy loading
This one is pure insane. If you use a DBRefs to refer to another document, Spring Mongo will pull out the entire document, instead of just the reference. So if you have a bunch of documents connected to each other via dbrefs, a small query where you really only want to access a couple fields will end up pulling out the entire document graph!
The fact that the bug report on this is almost 2 years old and has been assigned a ‘minor’ status with no resolution in sight is mindboggling, and shows how misaligned Spring Mongo’s visions are with its usage in the real world.
3. No cursor support
Want to use a cursor to stream and iterate through a collection. No dice. Either pull out the entire collection or fall back to the native Mongo Java driver.
4. Incomplete Aggregation framework support
Spring Mongo only very recently started supporting the Mongo Aggregation framework, and like the rest of Spring Mongo, it is a half hearted effort.
The framework documentation is sparse and confusing and most of your real world aggregation queries wont end up fitting with Spring Mongo’s implementation (not without nonsensical workarounds anyway); forcing you yet again to fall back to the native driver.
5. Incomplete Index support
While Spring will indeed allow you to mark a field as ‘indexed’, the rest of the operations don’t take that knowledge into account.
Take for example the fact that in Mongo, if a field is unique and sparse, you cannot insert it more than once into a document with a ‘null’ value. That means the second time when you do an insert, that field should just not be present in the first place.
However, since Spring forces you to define the fields of a document in a class, you will end up assigning null to a field which does not exist. And if the field has a unique, sparse index, this will result in a nasty runtime error, since Spring will not take the knowledge of the index in account when creating the query out of your entity object(which btw is defined as an annotation directly on the field).
Spring also has an
ensureIndex() method to manually create indexes on fields, without using annotations, but there are no guidelines whatsoever as to when and how frequently it should be called and what the performance implications of calling it are.
6. Cant switch database
A lot of times you will want to store data in different databases on a single instance of Mongo for things like keeping data of individual customers separate.
With the native Mongo driver, switching between the databases is a simple matter of calling
getDb(dbName). With Spring however, this is close to impossible unless you are willing to write a chunk of the framework yourself (which may change underneath you across releases).
7. Surprise Logging Framework
I have already written about Spring’s documentation issues. The Spring documentation says it uses Jakarta Commons Logging, but Spring Data apparently uses SLF4J. However, the Spring Data documentation makes absolutely no mention of this fact.
This means if you are starting out with Spring Data, your very first experience will consist of a bunch of undocumented runtime errors, which you will figure out only after banging your head for a few hours on Stack Overflow.
8. No support for dynamic nature of documents
The biggest reason to use a document-oriented database like MongoDb is for its dynamic nature. Things like the fact that one document can be different from the other, so I can have multiple versions in the same collection and progressively upgrade my users. Documents can be nested. Key names don’t have to be known in advance, so I can insert a map of properties directly into my document.
The fact that Spring Mongo discards this fundamental nature of Mongo and tries to make a fixed, pre-defined ORM style layer on top of it results in a complete mismatch between the framework and the database.
Spring Data MongoDB seems to be designed by somebody who has never used MongoDB in real life. It attempts to shoehorn a Document Oriented Database in an ORM style framework.
This results in a huge mismatch where Spring Mongo actually starts to become more of a hindrance than a help. It means you will end up mostly falling back to the native MongoDB Java driver in almost all real world projects.