Spring Data MongoDB-视图,@ CompoundIndex和注释继承

时间:2018-09-14 15:07:10

标签: spring inheritance view annotations spring-data-mongodb

我遇到了一个尝试将继承与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注释。

1 个答案:

答案 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注释。