Spring Data, Mongo, and @TypeAlias: reading not working
I spent a bunch of time with my debugger and the Spring Data source code, and I learned that Spring Data isn't as good as it probably should be with polymorphism as it should be, especially given the schema-less nature of NoSQL solutions like MongoDB. But ultimately what I did was to write my own type mapper, and that wasn't too tough.
The main problem was that, when reading in my Page document, the default mappers used by Spring Data would see a collection called widgets, then consult the Page class to determine that widgets pointed to a List, then consult the Widget class to look for @TypeAlias information. What I needed instead was a mapper that scanned my persistent entities up front and stored an alias-to-class mapping for later use. That's what my custom type mapper does.
I wrote a blog post discussing the details.
In the default setting, the MappingMongoConverter
creates a DefaultMongoTypeMapper
which in turn creates a MappingContextTypeInformationMapper
.
That last class is the one responsible for maintaining the typeMap
cache between TypeInformation
and aliases.
That cache is populated in two places:
- In the constructor, for each
mappingContext.getPersistentEntities()
- When writing an object of an aliased type.
So if you want to make sure the alias is recognized in any context, you need to make sure that all your aliased entities are part of mappingContext.getPersistentEntities()
.
How you do that depends on your configuration. For instance:
- if you're using
AbstractMongoConfiguration
, you can overwrite itsgetMappingBasePackage()
to return the name of a package containing all of your entities. - if you're using spring boot, you can use
@EntityScan
to declare which packages to scan for entities - in any case, you can always configure it with a custom set (from a static list or a custom scan) using
mongoMappingContext.setInitialEntitySet()
One side note, for an entity to be discovered by a scan, it has to be annotated with either @Document
or @Persitent
.
More informations can be found in the spring-data-commons Developer Guide