Spring 数据 MongoDB - 视图、@CompoundIndex 和注解继承
Spring Data MongoDB - Views, @CompoundIndex and annotation inheritance
我 运行 遇到一个问题,试图结合 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
class 以便我可以在从视图读取时利用其成员 getters/setters 等,如下所示:
@Document(collection = "itemsView")
public class ItemAvailable extends Item {
// Now I can read from the view but treat them as `Item` instances
}
知道无法在视图上创建索引,我检查了 Spring 数据 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: 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'
所以,Spring 毕竟是在尝试在视图上创建索引。
我正在尝试完成的工作似乎是处理视图(及其实体,毕竟它们只是 "normal" 非视图实体)时的常见设计挑战。
为什么将非继承的 @CompoundIndex
注释应用于子class?
更新:经过大量调试后,我相信这可能是 Spring 数据 MongoDB 中的错误。 MongoPersistentEntintyIndexResolver
有一个 potentiallyCreateCompoundIndexDefinitions
方法,该方法显式检查 @CompoundIndexes
和 @CompoundIndex
在相关 class (实体)上是否存在。它通过调用 Spring Data 的 BasicPersistentEntity.findAnnotation
方法来实现。该方法向上遍历继承链以查找指定的注释,如果找到则返回它 ,而不管它在 class 层次结构中的何处找到 。没有检查 potentiallyCreateCompoundIndexDefinitions
(或其他任何地方)以查看是否在 superclass 上找到注释,如果是,则是否存在 @Inherited
注释。
Spring 框架在查找注解时使用自己的逻辑,并默认检查已实现的接口和超 class 类型。 @Inherited
没有任何改变。
无论如何,我记得当我 运行 在类似的问题中时,无法避免继承复合索引。
Spring 数据 MongoDB 的 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.
来自 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.
因此,根据本文档,我遇到的行为是正确的。但是我认为这是 Spring 数据 MongoDB 的错误 - 为了正确尊重 @Inherited
它需要调用其中一种 get
注释方法而不是 find
方法以防止继承非 @Inherited
注释。
我 运行 遇到一个问题,试图结合 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
class 以便我可以在从视图读取时利用其成员 getters/setters 等,如下所示:
@Document(collection = "itemsView")
public class ItemAvailable extends Item {
// Now I can read from the view but treat them as `Item` instances
}
知道无法在视图上创建索引,我检查了 Spring 数据 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: 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'
所以,Spring 毕竟是在尝试在视图上创建索引。
我正在尝试完成的工作似乎是处理视图(及其实体,毕竟它们只是 "normal" 非视图实体)时的常见设计挑战。
为什么将非继承的 @CompoundIndex
注释应用于子class?
更新:经过大量调试后,我相信这可能是 Spring 数据 MongoDB 中的错误。 MongoPersistentEntintyIndexResolver
有一个 potentiallyCreateCompoundIndexDefinitions
方法,该方法显式检查 @CompoundIndexes
和 @CompoundIndex
在相关 class (实体)上是否存在。它通过调用 Spring Data 的 BasicPersistentEntity.findAnnotation
方法来实现。该方法向上遍历继承链以查找指定的注释,如果找到则返回它 ,而不管它在 class 层次结构中的何处找到 。没有检查 potentiallyCreateCompoundIndexDefinitions
(或其他任何地方)以查看是否在 superclass 上找到注释,如果是,则是否存在 @Inherited
注释。
Spring 框架在查找注解时使用自己的逻辑,并默认检查已实现的接口和超 class 类型。 @Inherited
没有任何改变。
无论如何,我记得当我 运行 在类似的问题中时,无法避免继承复合索引。
Spring 数据 MongoDB 的 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.
来自 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.
因此,根据本文档,我遇到的行为是正确的。但是我认为这是 Spring 数据 MongoDB 的错误 - 为了正确尊重 @Inherited
它需要调用其中一种 get
注释方法而不是 find
方法以防止继承非 @Inherited
注释。