I'm running into an issue trying to leverage inheritance in combination with MongoDB views and @CompoundIndex
. Say I have a collection items
and a view of that collection called itemsView
. I'm representing these entities in my models like so:
@Document(collection = "items")
@CompoundIndex(name = "view_active_available" def = "{active: 1, quantity: 1}")
public class Item {
// Adding index on collection that view definition will leverage
}
Then, for the view I want to extend the Item
class so that I can leverage its members, getters/setters, etc. when reading from the view, as such:
@Document(collection = "itemsView")
public class ItemAvailable extends Item {
// Now I can read from the view but treat them as `Item` instances
}
Knowing that it's not possible to create indexes on views I checked the Spring Data MongoDB source for the @CompoundIndex
annotation and found:
/**
* Mark a class to use compound indexes.
* ...
*/
@Target({ ElementType.TYPE })
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface CompoundIndex {
...
}
Perfect, @CompoundIndex
is not @Inherited
so this should work fine, I thought. So I built and fired up my app and sadly ran into this:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'itemsView': Invocation of init method failed;
nested exception is org.springframework.data.mongodb.UncategorizedMongoDbException: Command failed with error 166: 'Cannot create indexes on a view'
So, Spring is trying to create the index on the view after all.
What I'm trying to accomplish seems like it must be a common design challenge when working with views (and their entities, which are just a "normal" non-view entities after all).
Why is the non-inherited @CompoundIndex
annotation getting applied to the subclass?
Update: After doing extensive debugging I believe this may be a bug in Spring Data MongoDB. MongoPersistentEntintyIndexResolver
has a potentiallyCreateCompoundIndexDefinitions
method which explicitly checks for the presence of @CompoundIndexes
and @CompoundIndex
on the class (entity) in question. It does so by calling Spring Data's BasicPersistentEntity.findAnnotation
method. That method traverses up the inheritance chain looking for the specified annotation, returning it if it's found regardless of where in the class hierarchy it was found. There's no checking in potentiallyCreateCompoundIndexDefinitions
(or anywhere else) to see if the annotation was found on a superclass and if so whether or not the @Inherited
annotation was present.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…