本文介绍了Spring Data MongoDB - 视图、@CompoundIndex 和注解继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在尝试将继承与 MongoDB 视图和 @CompoundIndex 结合使用时遇到了问题.假设我有一个集合 items 和一个名为 itemsView 的集合视图.我在我的模型中表示这些实体,如下所示:

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
}

然后,对于视图,我想扩展 Item 类,以便在从视图中读取时可以利用其成员、getter/setter 等:

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
}

知道不可能在视图上创建索引,我检查了 @CompoundIndex 注释的 Spring Data MongoDB 源并发现:

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 {
    ...
}

完美,@CompoundIndex 不是 @Inherited 所以这应该可以正常工作,我想.所以我构建并启动了我的应用程序,但遗憾的是遇到了这个:

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:错误创建名为itemsView"的 bean:调用 init 方法失败;嵌套异常是 org.springframework.data.mongodb.UncategorizedMongoDbException:命令失败,错误 166:无法在视图上创建索引"

因此,Spring 正在尝试在视图上创建索引.

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).

为什么非继承的 @CompoundIndex 注释被应用到子类?

Why is the non-inherited @CompoundIndex annotation getting applied to the subclass?

更新:经过大量调试后,我认为这可能是 Spring Data MongoDB 中的一个错误.MongoPersistentEntintyIndexResolver 有一个 potentiallyCreateCompoundIndexDefinitions 方法,该方法显式检查类(实体)上是否存在 @CompoundIndexes@CompoundIndex) 的问题.它通过调用 Spring Data 的 BasicPersistentEntity.findAnnotation 方法来实现.该方法遍历继承链以查找指定的注释,如果找到则返回它不管它在类层次结构中的哪个位置找到.没有检查 potentiallyCreateCompoundIndexDefinitions(或其他任何地方)以查看是否在超类中找到了注释,如果是,则@Inherited 注释是否存在.

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.

推荐答案

Spring Data MongoDB 的 MongoPersistentEntityIndexResolver 调用内部私有方法potentiallyCreateCompoundIndexDefinitions,传入BasicPersistentEntity 它正在检查.该方法依次调用实体的 findAnnotation 方法,最终遵循 AnnotatedElementUtils.findMergedAnnotation.

Spring Data MongoDB's MongoPersistentEntityIndexResolver calls an internal private method potentiallyCreateCompoundIndexDefinitions, passing in the BasicPersistentEntity it's examining. That method in turn calls the entity's findAnnotation method which finally defers to AnnotatedElementUtils.findMergedAnnotation.

来自该课程的文档:

支持@Inherited

遵循 get 语义的方法将遵守 Java 的 @Inherited 注解的约定,除了本地声明的注解(包括自定义组合注解)将比继承注解更受青睐.相比之下,遵循 find 语义的方法将完全忽略 @Inherited 的存在,因为 find 搜索算法手动遍历类型和方法层次结构,从而隐式支持注解继承,而无需 @Inherited.

Methods following get semantics will honor the contract of Java's @Inherited annotation except that locally declared annotations (including custom composed annotations) will be favored over inherited annotations. In contrast, methods following find semantics will completely ignore the presence of @Inherited since the find search algorithm manually traverses type and method hierarchies and thereby implicitly supports annotation inheritance without a need for @Inherited.

因此,根据本文档,我遇到的行为是正确的.但是我相信这是 Spring Data MongoDB 的一个错误 - 为了正确尊重 @Inherited 它需要调用 get 注释方法之一而不是 find 方法以防止继承非@Inherited 注释.

So the behavior I'm experiencing is correct per this documentation. However I believe this is a bug with Spring Data MongoDB - to properly respect @Inherited it needs to call one of the get annotation methods instead of the find method in order prevent inheritance of non-@Inherited annotations.

这篇关于Spring Data MongoDB - 视图、@CompoundIndex 和注解继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-23 17:44