Spring Data MongoDB-视图,@ CompoundIndex和注释继承 [英] Spring Data MongoDB - Views, @CompoundIndex and annotation inheritance

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

问题描述

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

解决方案

Spring Data MongoDB的

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.

解决方案

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.

From the docs for that class:

Support for @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.

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和注释继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆