Как использовать NVL для получения данных из GemFire, когда результат запроса равен нулю - PullRequest
0 голосов
/ 15 февраля 2019

Я использую Spring Data GemFire ​​ в проекте, и я использую репозиторий для получения результатов запроса из кэша, как указано здесь: https://docs.spring.io/spring-gemfire/docs/1.3.3.RELEASE/reference/html/gemfire-repositories.html

Ниже приведен мой Репозиторий интерфейс:

@Repository
@Region("someRegion")
public interface SomeRegionRepository  extends GemfireRepository<CustomObject, Object> {

    //Below works when id exists in gemfire region. 
    //But when id does not exists it
    //gives java.lang.IllegalStateException: Unsupported query
    @Query("select a.num from /someRegion a where a.id = $1")
    Integer getNumById(String id);

    //Below returns CustomObject instance when id exists in gemfire region. 
    //But when id does not exists it returns null (Expected)
    CustomObject findById(String id);

}

Можно ли как-нибудь вернуть 0 или другое значение, если в запросе OQL не найдено данных для этого ключа?

Или есть ли способ получить значение null, чтобы я мог обработать его в коде вызывающего абонента при отсутствии данных?

В OQL указано следующее: https://gemfire.docs.pivotal.io/97/geode/developing/query_select/the_select_statement.html (что позволяет возвращать другое значение / выражения в случае, если первое выражение имеет значение null).Но я не могу получить правильный синтаксис того, как его использовать.

Пожалуйста, помогите.Спасибо.

1 Ответ

0 голосов
/ 15 февраля 2019

Во-первых, один предмет домашнего хранения, прежде чем мы начнем ...

Я вижу, что вы ссылались на Pivotal GemFire ​​ 9.7 в ссылке на документацию GemFire ​​выше, но затем ссылаетесь на Spring Data GemFire ​​ (SDG) 1.3.3.RELEASE Справочная документация.Я, конечно, надеюсь, что вы не пытаетесь использовать SDG 1.3.3.RELEASE с Pivotal GemFire ​​9.7.SDG 1.3.3 довольно устарел, основан на Pivotal GemFire ​​7.0.1 и больше не поддерживается.

Я подозреваю, что вы не используете SDG 1.3.x, поэтому вам, вероятно, следует всегда ссылаться на последнюю доступную документацию здесь и, в частности, здесь .Даже Поиск Google показывает последние документы.

Кроме того, вы можете обратиться к Spring Data для Pivotal GemFire ​​ Матрица совместимости версий для получения дополнительной информации.подробности.Во всяком случае ...

Итак, я написал тестовый класс , чтобы лучше понять ваш UC.

В своем тесте я смоделировал класс Person с запросом age поле / свойство .У меня есть PersonRepository для типа Person, и я написал очень похожий запрос к вашему примеру выше, чтобы запросить человека по возрасту, в обычно , а также null-safe манера.

Дело в том, что ваше желание хотеть защитить от отсутствия результатов путем возврата null или 0 неоднозначно в случае Репозитории .

Для 1, если вы вернули несколько результатов (например, как в SELECT a.num FROM /SomeRegion a; т.е. без предиката), и результаты не были упорядочены, то у вас не будет возможности узнать, какое значение былоnull для какого ключа, если только вы не вернули ключ в наборе результатов.

Конечно, это не тот случай, и вы квалифицировали запрос по идентификатору с использованием предиката (то есть ... WHERE a.id = $1).Однако в этом случае неясно, просматривая запрос (т. Е. SELECT a.num FROM ...), не было ли результата для данного идентификатора (т. Е. Ключа) или просто num было null.Вы действительно не знаете.

Мой тест продолжается, чтобы проиллюстрировать этот момент.

У меня 2 человека ["Jon Doe", "Jane Doe"], здесь .Джон имеет объявленный возраст, а Джейн - нет.Конечно, оба человека существуют в кеше (т. Е. Область «Люди»).

Когда я запрашиваю Джона и утверждаю его возраст, я получаю ожидаемый результат .

В качестве альтернативы, когда я запрашиваю Джейн и утверждаю ее возраст, я могу получить 1 из двух значений: null или 0, как ожидается (в настоящее время 0, поскольку я использую нулевой безопасный запрос ).Если я изменю запрос на обычный запрос , тогда возвращаемое значение для age Джейн будет на самом деле null, и я могу утверждать так.

Однако, когда мыприступить к опросу несуществующего человека, поведение GemFire ​​понятно;нет результатов.Я проиллюстрировал это двумя различными способами (кроме использования репозитория), используя GemFire ​​QueryService API напрямую, а затем снова используя SDG удобный GemfireTemplate класс , который просто оборачивает GemFireAPI запросов (это также метод, который используется Repository под капотом; на самом деле, значение Repositories добавляет возможности сопоставления / преобразования).

Как видите, я должен разобратьсяотсутствие результатов, например, .

В случае с репозиторием, поскольку вы использовали пользовательский запрос, для инфраструктуры репозитория не сразу видно, какая часть (т.е. промежуточный результат запроса) был null.

Что если у вас было SELECT person.address.city.name FROM ...?

Является ли человек null, адрес null или город null?Как это должно обрабатываться последовательно?Человек может выйти, но адрес может быть null, что может оправдать другое поведение, чем если бы человек или город были null.

На самом деле абстракция Репозиторий обрабатывает null возвращаемые значения, как видно здесь .

Итак, куда мы пойдем отсюда?

У нас есть несколько вариантов:

  1. Вы могли бы и проверить существование , сначала ...

    вернуть personRepository.existsById (bobDoe.getName ())?personRepository.getAge (bobDoe.getName ()): 0;

  2. Вы можете справиться с этим вне репозитория в DAO (возможно, адаптируя / декорируя Репозиторий и делегирование для простых случаев запросов, а не сложных запросов, которые включают использование аннотации @Query, которую следует использовать с осторожностью).

    @ Класс репозитория PersonDao {

    @Autowired
    private PersonRepository personRepository;
    
    Person findById(String name) {
        return this.personRepository.findById(name).orElse(null);
    }
    
    Integer getAge(String name) {
        // Either use the approach in #1, or do https://github.com/jxblum/contacts-application/blob/master/tests-example/src/test/java/example/tests/spring/data/gemfire/NullValueReturningRepositoryQueryMethodIntegrationTests.java#L143-L151.
    }
    
    ...
    

    }

    Все еще

  3. Другой вариант - предоставить нам дополнительную поддержку в SD, что-то вроде ...

    @Nullable Integer getAge(String name);

    Или, возможно ...

    Optional<Integer> getAge(String name);

    Тем не менее, этот подход не решает проблему неоднозначности и потребует больше размышлений.

  4. Что было бы действительно хорошо, если бы OQL обрабатывал оператор Элвиса, что-то вроде (в моем более сложном примере выше) ...

    SELECT person? .Address? .City? .Name FROM /Люди ...

В любом случае, я надеюсь, что это даст вам некоторые идеи.Прежде чем двигаться дальше, мне нужно больше подумать над № 3.

Если у вас есть дополнительные вопросы / отзывы / идеи, пожалуйста, укажите их в комментариях или не стесняйтесь подавать билет JIRA .

Спасибо!

...