Как стать автором
Обновить

Создание кастомного генератора запросов в Spring Data Neo4j (Часть 1)

Время на прочтение3 мин
Количество просмотров2.1K

Начну с того, что появилась задача генерировать cypher-запросы по дата-классам на основе аннотаций @NodeEntity, @RelationshipEntity и @Relationship и дополнительных параметров. Был написан генератор запросов, однако строка запроса вычислялась в рантайме и мы не могли использовать ее в качестве параметра существующей аннотации @Query, поэтому была добавлена новая аннотация @CustomQuery, обработчик которой использовал написанный генератор запросов.


Версии использованного ПО:


spring-data-neo4j — 5.0.9.RELEASE
neo4j — 3.4.6
neo4j-ogm — 3.1.4


Добавление кастомного генератора запросов в Spring Data Neo4j


Для добавления своего механизма генерации cypher-запросов для методов neo4j-репозиториев, помеченных, например, аннотацией @CustomQuery необходимо создать класс CustomNeo4jRepositoryFactory extends Neo4jRepositoryFactory и переопределить в нем метод getQueryLookupStrategy, он должен возвращать новую стратегию поиска обработчиков query-аннотаций CustomGraphQueryLookupStrategy extends GraphQueryLookupStrategy:


@Override
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(QueryLookupStrategy.Key key, EvaluationContextProvider evaluationContextProvider) {
    return Optional.of(new CustomGraphQueryLookupStrategy(session));
}

Также необходимо расширить стандартный класс Neo4jRepositoryFactoryBean новым классом CustomNeo4jRepositoryFactoryBean и переопределить метод createRepositoryFactory. Он должен возвращать экземпляр новой фабрики репозиториев:


@Override
protected RepositoryFactorySupport createRepositoryFactory(Session session) {
    return new CustomNeo4jRepositoryFactory(session);
}

Чтобы Spring Data Neo4j понял, какой бин фабрики репозиториев использовать, его необходимо явно указать в аннотации @EnableNeo4jRepositories в конфигурации:


@EnableNeo4jRepositories(..., repositoryFactoryBeanClass = CustomNeo4jRepositoryFactoryBean.class)

Была введена дополнительная query-аннотация CustomQuery. Если метод репозитория помечен такой аннотацией, то CustomGraphQueryLookupStrategy в переопределенном методе resolveQuery будет возвращать объект нашего запроса CustomGraphRepositoryQuery extends GraphRepositoryQuery:


public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory, NamedQueries namedQueries) {
    if (method.isAnnotationPresent(CustomQuery.class)) {
        GraphQueryMethod queryMethod = new GraphQueryMethod(method, metadata, factory);
        return new CustomGraphRepositoryQuery(queryMethod, session, method.getAnnotation(CustomQuery.class));
    } else {
        return super.resolveQuery(method, metadata, factory, namedQueries);
    }
}

CustomGraphRepositoryQuery реализует метод getQuery, возвращающий объект Query, его конструктор принимает cypher-запрос, который был построен в CustomGraphRepositoryQuery на основе данных аннотации CustomQuery и объекта метода Method, помеченного такой аннотацией:


@Override
protected Query getQuery(Object[] parameters) {
    return new Query(query, resolveParams(parameters));
}

Метод resolveParametres(Object[]) и используемый им getParameterValue(Object) являются приватными в GraphRepositoryQuery, поэтому они были просто скопированы в CustomGraphRepositoryQuery (можно использовать рефлексию, это не повлияет на производительность, т.к. генерация запросов происходит до рантайма).


Заключение


Таким образом можно объявить свой механизм генерации cypher-запросов, если в этом есть необходимость.


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

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Интересно ли увидеть следующие части статьи?
62.5% да5
37.5% нет3
Проголосовали 8 пользователей. Воздержались 6 пользователей.
Теги:
Хабы:
Всего голосов 5: ↑2 и ↓3-1
Комментарии0

Публикации