Можно ли выполнять запросы к вложенным полям при использовании пользовательского класса в качестве ключа Ignite? - PullRequest
0 голосов
/ 23 апреля 2020

Используя Apache Ignite 2.7.6, я пытаюсь создать кеш, ключ которого является пользовательским классом с несколькими полями в нем, и который встроен в значение. Кеш работает, но интерфейс SQL показывает мне нулевые значения для полей во вложенном ключе. Более того, когда я делаю эти поля первичным ключом таблицы, результаты, кажется, нарушают стандарт SQL, поскольку в первичном ключе допускается использование нескольких нулевых значений. Есть ли способ заставить эту работу?

Ниже приведен воспроизводимый пример:

@Test
public void testComplexKey() throws InterruptedException {
    val queryEntity = new QueryEntity(TestKey.class, TestValue.class);
    // I get the same results regardless of whether these 2 lines are present or not
    queryEntity.getFields().put("key", TestKey.class.getName());
    queryEntity.setKeyFieldName("key");
    // I get the same results regardless of whether this lines is present or not
    queryEntity.setKeyFields(Sets.newHashSet("key.firstName", "key.lastName"));
    queryEntity.getFields().put("key.firstName", String.class.getName());
    queryEntity.getFields().put("key.lastName", String.class.getName());
    queryEntity.getFields().put("data", String.class.getName());
    queryEntity.setTableName("test_values");
    val cache = ignite.getOrCreateCache(
            new CacheConfiguration<TestKey, TestValue>()
                    .setName("test_values")
                    .setQueryEntities(Lists.newArrayList(queryEntity))
    );
    cache.put(new TestKey("Bob", "Jones"), new TestValue(new TestKey("Bob", "Jones"), "The quick red fox jumped over the lazy brown dog"));
    cache.put(new TestKey("Jim", "Smith"), new TestValue(new TestKey("Jim", "Smith"), "The quick red dog jumped over the lazy brown fox"));
    Assertions.assertEquals("The quick red fox jumped over the lazy brown dog", cache.get(new TestKey("Bob", "Jones")).data);
    // This assertion would fail - no rows found
    // Assertions.assertEquals("The quick red fox jumped over the lazy brown dog", cache.query(new SqlQuery<TestKey, TestValue>(TestValue.class, "firstName = 'Bob'")).getAll().stream().findFirst().orElseThrow().getValue().data);
    // This just to keep the test running and allow me to query the SQL interface
    while (true) Thread.sleep(10000);
}

@NoArgsConstructor // This is Lombok shorthand
@AllArgsConstructor
public static class TestKey {
    @Getter
    @Setter
    String firstName;

    @Getter
    @Setter
    String lastName;
}

@NoArgsConstructor
@AllArgsConstructor
public static class TestValue {
    @Getter
    @Setter
    TestKey key;

    @Getter
    @Setter
    String data;
}

Полученное представление SQL выглядит ... довольно запутанно:

SQL View depicting two rows both with NULL/NULL primary key values

1 Ответ

2 голосов
/ 23 апреля 2020

В механизме SQL все ваши объекты "сплющены", поэтому вы ссылаетесь на key.firstName так же, как firstName.

queryEntity.setKeyFields(Sets.newHashSet("firstName", "lastName"));
queryEntity.getFields().put("firstName", String.class.getName());
queryEntity.getFields().put("lastName", String.class.getName());
queryEntity.getFields().put("data", String.class.getName());

Большинству людей проще использовать @QuerySqlField аннотация к свойствам, которые вы хотите предоставить SQL.

Нет необходимости включать ключевой объект в значение. Удаление также приведет к удалению неоднозначности, на которую указывает столбец «firstName».

...