Spring Data MongoDB - представления, @CompoundIndex и наследование аннотаций - PullRequest
0 голосов
/ 14 сентября 2018

Я сталкиваюсь с проблемой, пытающейся использовать наследование в сочетании с представлениями 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, чтобы я мог использовать его члены, методы получения / установки и т. Д., Когдачтение из представления, как таковое:

@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: Ошибка при создании bean-компонента с именем itemsView: сбой вызова метода init;вложенное исключение: org.springframework.data.mongodb.UncategorizedMongoDbException: команда завершилась с ошибкой 166: «Не удается создать индексы для представления»

Итак, Spring пытается создать индекс для представления после всех.

То, что я пытаюсь выполнить, похоже, должно быть обычной проблемой проектирования при работе с представлениями (и их сущностями, которые, в конце концов, являются просто "обычными" не-сущностями).

Почему ненаследуемая аннотация @CompoundIndex применяется к подклассу?


Обновление: после обширной отладки я считаю, что это может быть ошибкой в ​​Spring DataMongoDB.У MongoPersistentEntintyIndexResolver есть метод potentiallyCreateCompoundIndexDefinitions, который явно проверяет наличие @CompoundIndexes и @CompoundIndex в рассматриваемом классе (сущности).Это делается путем вызова метода Spring Data BasicPersistentEntity.findAnnotation.Этот метод пересекает цепочку наследования в поисках указанной аннотации, возвращая ее, если она найдена независимо от того, где в иерархии классов она была найдена potentiallyCreateCompoundIndexDefinitions (или где-либо еще) не проверяется, была ли найдена аннотация в суперклассе, и если да, присутствовала ли аннотация @Inherited.

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Spring Data MongoDB MongoPersistentEntityIndexResolver вызывает внутренний закрытый метод potentiallyCreateCompoundIndexDefinitions, передавая BasicPersistentEntity , который он исследует.Этот метод, в свою очередь, вызывает метод findAnnotation объекта, который в конечном итоге обращается к AnnotatedElementUtils.findMergedAnnotation .

Из документов этого класса:

Поддержка @ Inherited

Методы, следующие за семантикой get, будут соблюдать контракт аннотации @Inherited Java, за исключением того, что локально объявленные аннотации (включая пользовательские составные аннотации) будут предпочтительнее, чем унаследованные аннотации.Напротив, методы, следующие за семантикой поиска, полностью игнорируют присутствие @Inherited, поскольку алгоритм поиска поиска вручную обходит иерархии типов и методов и тем самым неявно поддерживает наследование аннотаций без необходимости @ Inherited.

Так чтоповедение, которое я испытываю, является правильным согласно этой документации.Однако я считаю, что это ошибка в Spring Data MongoDB - для правильного соблюдения @Inherited необходимо вызвать один из методов аннотации get вместо метода find, чтобы предотвратить наследование аннотаций не @Inherited.

0 голосов
/ 14 сентября 2018

Spring Framework использует собственную логику при поиске аннотаций и по умолчанию проверяет реализованные интерфейсы и типы суперкласса.@Inherited ничего не меняет.

Во всяком случае, насколько я помню, когда я столкнулся с подобной проблемой, нет способа избежать наследования составных индексов.

...