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]
我有两个缓存,一个用于 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]