我遇到了一个尝试将继承与MongoDB视图和@CompoundIndex
结合使用的问题。假设我有一个集合items
和一个名为itemsView
的集合视图。我在模型中代表这些实体,如下所示:
@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
}
然后,对于视图,我想扩展Item
类,以便在从视图中读取时可以利用其成员,getter / setter等,例如:
@Document(collection = "itemsView")
public class ItemAvailable extends Item {
// Now I can read from the view but treat them as `Item` instances
}
知道无法在视图上创建索引,我检查了Spring Data MongoDB源的@CompoundIndex
批注,发现:
/**
* Mark a class to use compound indexes.
* ...
*/
@Target({ ElementType.TYPE })
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface CompoundIndex {
...
}
完美,@CompoundIndex
不是@Inherited
,所以我认为这应该可以正常工作。因此,我构建并启动了我的应用程序,可悲地遇到了这个问题:
org.springframework.beans.factory.BeanCreationException:错误 创建名称为“ itemsView”的bean:调用init方法失败; 嵌套异常是org.springframework.data.mongodb.UncategorizedMongoDbException:命令失败,错误166:“无法在视图上创建索引”
因此,Spring毕竟试图在视图上创建索引。
我要完成的工作似乎在处理视图(及其实体,毕竟它们只是“普通”非视图实体)时必须是一个常见的设计挑战。
为什么非继承的@CompoundIndex
注释会应用于子类?
更新:经过大量调试,我相信这可能是Spring Data MongoDB中的错误。 MongoPersistentEntintyIndexResolver
有一个potentiallyCreateCompoundIndexDefinitions
方法,该方法显式检查所讨论的类(实体)上是否存在@CompoundIndexes
和@CompoundIndex
。通过调用Spring Data的BasicPersistentEntity.findAnnotation
方法来做到这一点。该方法遍历继承链以查找指定的注释,如果找到了,无论其在类层次结构中的什么位置,都将其返回。没有检查potentiallyCreateCompoundIndexDefinitions
(或其他任何地方)以查看是否在超类上找到了注释,以及是否存在@Inherited
注释。
答案 0 :(得分:0)
Spring Data MongoDB的MongoPersistentEntityIndexResolver调用内部私有方法potentiallyCreateCompoundIndexDefinitions
,并传入正在检查的BasicPersistentEntity。该方法继而调用实体的findAnnotation方法,该方法最终遵从AnnotatedElementUtils.findMergedAnnotation。
来自该类的文档:
支持@Inherited
遵循get语义的方法将遵守Java的@Inherited批注的约定,除了在本地声明的批注(包括自定义组成的批注)优于继承的批注之外。相反,遵循find语义的方法将完全忽略@Inherited的存在,因为find搜索算法手动遍历类型和方法层次结构,从而隐式支持注释继承,而无需@Inherited。
因此,根据此文档,我遇到的行为是正确的。但是,我认为这是Spring Data MongoDB的一个错误-为了正确遵守@Inherited
,它需要调用get
注释方法之一而不是find
方法,以防止非@Inherited
注释。