GridGain Developers Hub

Cache Storage

GridGain Caches are designed as temporary storage for rapid response "cache" of data that may be required for local operation.

Cache data is always stored in a special cache store. By default, the cache maintains a weak consistency with the remote storage.

Difference Between Caches and Tables

Unlike tables, in GridGain caches do not have persistence or store transaction history.

This means that caches also do not support read-only transactions and continuous queries, as those features rely on transaction history to ensure consistency.

Additionally, fields in caches cannot be nullable.

Creating a Cache

Caches are created by using the DDL CREATE CACHE command, for example:

CREATE ZONE CACHES WITH STORAGE_PROFILES='in-memory'"

CREATE CACHE Accounts (
    accountNumber INT PRIMARY KEY,
    firstName VARCHAR,
    lastName VARCHAR,
    balance DOUBLE
) WITH PRIMARY_ZONE = 'CACHES';

Caches as External Storage

GridGain Caches do not need to be linked to a GridGain Database. You can connect a cache to an external storage by using JDBC connection, and read data directly from it if required data is not available in the cache, or write data that was sent to cache into it.

You can use tuples or POJOs to work with the database. In the examples below we will use the following POJOs for POJO examples:

static class AccountKey {
    int accountNumber;

    /**
     * Default constructor (required for deserialization).
     */
    @SuppressWarnings("unused")
    public AccountKey() {
    }

    public AccountKey(int accountNumber) {
        this.accountNumber = accountNumber;
    }
}

/**
 * POJO class that represents value.
 */
static class Account {
    String firstName;
    String lastName;
    double balance;

    /**
     * Default constructor (required for deserialization).
     */
    @SuppressWarnings("unused")
    public Account() {
    }

    public Account(String firstName, String lastName, double balance) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.balance = balance;
    }
}
// Tuple objects are created in code samples.

To connect to an external database:

  • Configure the connection to the external database:

    JdbcConnectionPool dataSrc = JdbcConnectionPool.create("jdbc:h2:mem:GridGainKeyValueViewExample", "sa", "")
  • Configure a cache store factory:

    // Create a store factory object
    JdbcCacheStoreFactory storeFactory = new JdbcCacheStoreFactory();
    
    // Set the storage dialect
    // Supported dialects: DB2Dialect, H2Dialect, JdbcDialect, MySQLDialect, OracleDialect, SQLServerDialect.
    storeFactory.setDialect(new H2Dialect());
    
    // Create a JDBC type object will be used to store data.
    JdbcType jdbcType = new JdbcType();
    
    // Set the table schema.
    jdbcType.setDatabaseSchema("PUBLIC");
    
    // Set the name of the table to connect the cache to.
    jdbcType.setDatabaseTable("Accounts");
    
    // Set the key configuratin in the object matched to the columns of the underlying database.
    jdbcType.setKeyType(Person.class);
    jdbcType.setKeyFields(new JdbcTypeField(Types.INTEGER, "accountNumber", Integer.class, "accountNumber"));
    
    // Create a mapping for column values of the underlying database.
    jdbcType.setValueType(Account.class);
    jdbcType.setValueFields(
        new JdbcTypeField(Types.VARCHAR, "firstName", String.class, "firstName"),
        new JdbcTypeField(Types.VARCHAR, "lastName", String.class, "lastName"),
        new JdbcTypeField(Types.DOUBLE, "balance", Double.class, "balance")
    );
    
    // Set the created type object as the store factory data type.
    storeFactory.setType(jdbcType);
    // Set the store factory to connect to the database.
    storeFactory.setDataSource(dataSrc);
    // Create a store factory object
    JdbcCacheStoreFactory storeFactory = new JdbcCacheStoreFactory();
    
    // Set the storage dialect
    // Supported dialects: DB2Dialect, H2Dialect, JdbcDialect, MySQLDialect, OracleDialect, SQLServerDialect.
    storeFactory.setDialect(new H2Dialect());
    
    // Create a JDBC type object will be used to store data.
    JdbcType jdbcType = new JdbcType();
    
    // Set the table schema.
    jdbcType.setDatabaseSchema("PUBLIC");
    
    // Set the name of the table to connect the cache to.
    jdbcType.setDatabaseTable("Accounts");
    
    // Set the key configuratin in the object matched to the columns of the underlying database.
    jdbcType.setKeyType(Tuple.class);
    jdbcType.setKeyFields(new JdbcTypeField(Types.INTEGER, "accountNumber", Integer.class, "accountNumber"));
    
    // Create a mapping for column values of the underlying database.
    jdbcType.setValueType(Tuple.class);
    jdbcType.setValueFields(
        new JdbcTypeField(Types.VARCHAR, "firstName", String.class, "firstName"),
        new JdbcTypeField(Types.VARCHAR, "lastName", String.class, "lastName"),
        new JdbcTypeField(Types.DOUBLE, "balance", Double.class, "balance")
    );
    
    // Set the created type object as the store factory data type.
    storeFactory.setType(jdbcType);
    // Set the store factory to connect to the database.
    storeFactory.setDataSource(dataSrc);
  • Create a key-value view for the table in the underlying database:

    KeyValueView<AccountKey, Account> kvView = client.caches().cache("accounts").keyValueView(storeFactory, Mapper.of(AccountKey.class), Mapper.of(Account.class));
    // Get the cache Person
    Cache cache = client.caches().cache("Accounts");
    
    // Make sure there are no null values in the table.
    Objects.requireNonNull(cache);
    
    // Create a key-value view
    KeyValueView<Tuple, Tuple> kvView = cache.keyValueView(storeFactory);

The cache is now connected to the database. Write operations to the cache will be propagated to the database, and data missing in the cache will be retrieved automatically. For example, here is how you can retrieve a key:

// Create a key1 tuple and retrieve a value.
// If it is not present in the cache, it will be read from the database.
AccountKey key1 = new AccountKey(123);
value = kvView.get(null, key);

// Create a key2 tuple and write to the cache and database.
AccountKey key2 = new AccountKey(1234);
Account value = new Account(
    "John",
    "Smith",
    100
);
kvView.put(null, key, value);
// Create a key1 tuple and retrieve a value.
// If it is not present in the cache, it will be read from the database.
Tuple key1 = Tuple.create().set("id", 123);
value = kvView.get(null, key1);

// Create a key2 tuple and write to the cache and database.
Tuple key2 = Tuple.create().set("id", 1234);
Tuple value = Tuple.create()
    .set("firstName", "John")
    .set("lastName", "Smith")
    .set("balance", 100);

kvView.put(null, key2, value);