Используя 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](https://i.stack.imgur.com/uh0fx.png)