[使用Apache Ignite 2.7.6,我正在尝试创建一个缓存,该缓存的键是其中包含多个字段的自定义类,并且将其嵌入值中。缓存有效,但是SQL界面向我显示了嵌套键中字段的空值。而且,当我将这些字段设为表的主键时,结果似乎违反了标准SQL,因为在主键中允许多个null值。有什么办法可以使这项工作吗?
以下是可复制的示例:
@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引擎中,所有对象都被“展平”,因此您将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());
大多数人发现在要公开给SQL的属性上使用@QuerySqlField
批注更容易。
无需在值中包含键对象。删除它还会消除您所引用的“ firstName”列的歧义。