Apache Ignite:如何在没有关联键的情况下获取缓存项

Apache Ignite: How to get cached item without affinity key

我有两个缓存,一个用于 Person,另一个用于 Company 对象,通过指定 Person.Id 作为键和 Person.CompanyId 作为关联键。

personCache.Put(new AffinityKey(p1.Id, p1.CompanyId), p1);
companyCache.Put(c1.Id, c1);

是否可以使用 Person.Id 从缓存中获取人物? (没有 Person.CompanyId)?

是,但不是键值 API。

Key-Value API,根据定义,需要密钥才能访问数据。如果您的密钥是 AffinityKey(personId, companyId) 那么您必须构建完整的密钥对象才能使用 IgniteCache::get 操作。

但是,还有SQL API,这是访问相同数据的另一个接口。您可以将缓存声明为启用 SQL 的缓存,并将 personId 声明为该缓存中的 SQL 字段。

有多种方法可以创建启用 SQL 的缓存:

  • 使用 CREATE TABLE 语句创建它(而不是在节点配置中指定它或使用 createCache 方法创建)。

  • 指定indexedTypes作为CacheConfiguration的一部分,将键值对象的字段注释为@QuerySqlField.
    indexedTypes 的问题在于您必须将注释放入 classes 中。显然,这不适用于 AffinityKey class,因为您无法更改它。

  • QueryEntity 指定为 CacheConfiguration 的一部分。
    QueryEntity 的问题在于它可能会变得相当复杂,并且通常比 @QuerySqlField 注释更难维护。

对于你的情况,我建议不要使用 AffinityKey class 并创建你自己的版本 - 让我们称之为 PersonKey。您可以注释其字段并使用 indexedTypes.

下面是一个简短的例子:

public class SqlFieldInKeyExample {
    static class PersonKey {
        @QuerySqlField
        long personId;

        @QuerySqlField
        @AffinityKeyMapped
        long companyId;

        public PersonKey(long personId, long companyId) {
            this.personId = personId;
            this.companyId = companyId;
        }
    }

    static class Person {
        @QuerySqlField
        String name;

        public Person(String name) {
            this.name = name;
        }
    }

    public static void main(String[] args) throws IgniteException {
        try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) {
            CacheConfiguration<PersonKey, Person> cfg = new CacheConfiguration<PersonKey, Person>()
                .setName("PersonCache")
                .setIndexedTypes(PersonKey.class, Person.class);

            IgniteCache<PersonKey, Person> cache = ignite.createCache(cfg);

            cache.put(new PersonKey(9000, 42), new Person("John Doe"));

            List<List<?>> result = cache.query(new SqlFieldsQuery("SELECT * FROM PERSON WHERE PERSONID = 9000")).getAll();
            assert result.size() == 1;
            System.out.println(">>>>> Person: " + result.get(0));
        }
    }
}

输出(除其他外)是:

>>>>> Person: [9000, 42, John Doe]