Persisting data to MySQL

In this section, we will create a model Java class, 'conference', and persist it to a MySQL table. We already installed MySQL in Chapter 2, Understanding the Topologies and Caching Strategies. Let's reuse the MySQL instance to persist cache data.

Create a Java program, store objects into a cache, and then persist the cached data to a MySQL table. Follow this process to persist data to a MySQL table:

  1. Modify the build.gradle file and add a dependency for the MySQL client with the compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.11' command.
  2. Create a schema called 'persistence' and add a new table called 'conference' with the following DDL:
      CREATE TABLE `persistence`.`conference` (
`id` INT(10) NOT NULL,
`name` VARCHAR(45) NOT NULL,
`startDateTime` DATETIME NOT NULL,
`endDateTime` DATETIME NOT NULL,
PRIMARY KEY (`id`));
  1. Launch the My SQL workbench, connect to your database, expand the Schemas section, and right-click on Tables:

  1. Click on the Create table sub-menu and create our new Conference table:

  1. Create a Java model called Conference.java with the following fields: id = conference identifier, name = name of the conference, startDateTime = when the conference will start, and endDateTime = when the conference will end:
      class Conference implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private Date startDateTime;
private Date endDateTime;
//getter/setters
}

Ignite's CacheStore<K, V> interface provides APIs for cache persistent storage for read-through, write-through, and write-behind behavior. It extends the CacheWriter and CacheLoader interface. 

CacheLoader is used to read through or load data into a cache. It has a V load(K key) method to load a value for a cache entry. The cache calls this method when a requested entry is not yet loaded in the cache. Map<K, V> loadAll(Iterable<? extends K> keys) loads multiple objects into a cache.

CacheWriter is used to write through to persistent storage. The persistent storage could be a filesystem, a NoSQL database, a RDBMS, or any external storage where you want to store the cache entries. It defines the void write(Cache.Entry<? extends K, ? extends V> entry) and void writeAll(Collection<Cache.Entry<? extends K, ? extends V>> entries) methods for writing the specified entries to persistent storage. The developer has to understand the difference between insert and update. The simplest way is to check the id/key field of the value object. If the id is null or 0, then use insert; otherwise, use update.

The CacheStore interface has the following out-of-the-box implementations. Check that CacheJdbcPojoStore can persist a POJO (Plain Old Java Object) to database storage using reflection and JDBC support. GridCacheWriteBehindStore enables write-behind logic. CacheStoreAdapter is an abstract class and it provides default implementation for bulk operations, such as loadAll, writeAll, and deleteAll, by sequentially calling the corresponding load, write, and delete methods. You still need to implement the load, write, and delete methods.

  1. Create a CacheStoreAdapter to store the Conference objects to a database table. We need to implement thloadwrite, and delete methods. To persist the values to a database table we are going to need a database connection. In this example, we'll configure a Spring JDBC template bean and inject it to our CacheStoreAdapter.
The @SpringResource(resourceName=<<name>>) annotation injects the <<name>> resource from Spring ApplicationContext, before injecting the resource we need to define it (the name should match) in the Spring application context of the XML configuration. 
  1. Add a ConferenceCacheStore class and extend it from the CacheStoreAdapter class. It will use the @SpringResource annotation to inject a jdbcTemplate for JDBC operations. We will define jdbcTemplate and other Spring beans shortly. It will have the following methods:
    • load(Long key): Loads the key from the Conference table using the jdbcTemplate queryForObject API and the SELECT query.
    • write(Entry<Long, Conference> entry): Inserts a conference object to a Conference table using the update method of jdbcTemplate. We can build intelligence by checking the getId() method on the Conference object. If it is null, then execute the insert query; otherwise, execute the update query.
    • delete(Object key): Deletes the key from Conference table using SQL's DELETE query:
              public class ConferenceCacheStore extends 
CacheStoreAdapter<Long, Conference> {
@SpringResource(resourceName = "jdbcTemplate")
private JdbcTemplate jdbc;

@Override
public Conference load(Long key) throws CacheLoaderException
{
System.out.println(jdbc);
RowMapper<Conference> rowMapper = new
BeanPropertyRowMapper<Conference>(Conference.class);
return jdbc.queryForObject(String.format("SELECT * FROM
CONFERENCE WHERE ID=%s", key),
rowMapper);
}
@Override
public void write(Entry<? extends Long, ? extends Conference>
entry) throws CacheWriterException {
Conference conf = entry.getValue();
System.out.println(entry);
jdbc.update("INSERT INTO CONFERENCE(id, name, startDateTime,
endDateTime) VALUES(?, ?, ? ,?)" conf.getId(),
conf.getName(),
conf.getStartDateTime(), conf.getEndDateTime());
}
@Override
public void delete(Object key) throws CacheWriterException {
jdbc.update("DELETE FROM CONFERENCE WHERE ID =?", key);
}
}
  1. Create a spring application context XML configuration file called cache-config.xml, save it in the /src/main/resourcecs/META-INF/ folder, and define the following beans:
    • A dataSource with a driver class, URL, username, and password.
    • A jdbcTemplate with the dataSource reference. This bean will be injected to our CacheStoreAdapter.
    • Configure an IgniteConfiguration for our conferenceCache. Define a CacheConfiguration with the following:
      • name = 'conferenceCache'
      • readThrough=true: Enables read-through. It will call the CacheLoader's load method if an entry is not found in cache. The Conference load(Long key) method will be invoked.
      • writeThroug=true: Enables write-through. When an entry will be put or updated in the cache, internally the void write(Entry<? extends Long, ? extends Conference> entry) of CacheWriter (CacheStoreAdapter ) will be called to persist the entry to an external store (a database, in this case).
      • cacheStoreFactory withConferenceCacheStore: This attribute determines which CacheStore implementation will persist/load our cache entries:

 

<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3366/persistence"></property>
<property name="username" value="root"></property>
<property name="password" value="password"></property>
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>

<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="clientMode" value="true" />
<property name="cacheConfiguration">
<list>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="conferenceCache"></property>
<property name="readThrough" value="true"></property>
<property name="writeThrough" value="true"></property>
<property name="cacheStoreFactory">
<bean class="javax.cache.configuration.FactoryBuilder"
factory-method="factoryOf">
<constructor-arg value="com.persistence.rdbms.ConferenceCacheStore"/>
</bean>
</property>
</bean>
</list>
</property></bean>
  1. Create a Java class to read the cache-config.xml Spring beans and start an Ignite instance. As we have already defined the Ignite configuration to start a client node, it will launch a client instance, get the conferenceCache reference, and finally, put two Conference objects into our cache. In turn, the objects will be written to our conference table:
public class MySQLPersistenceTest {
public static void main(String[] args) {
Ignite ignite = Ignition.start("cache-config.xml");
ignite.cluster().active(true);
IgniteCache<Long, Conference> cache = ignite.getOrCreateCache("conferenceCache");
cache.loadCache(null);
cache.put(1l, new Conference(1l, "GOTO;", new Date(), new Date()));
cache.put(2l, new Conference(2l, "StrangeLoop;", new Date(), new Date())); System.out.println("done");
}
}
  1. Build the project and put the service .jar and mysql client .jar in the lib folder of our Ignite installation folder:

  • Now we need an Ignite server instance to store the cache and write the cache entries back to our persistent store. The server instance must know about dataSource and jdbcTemplate because the service code will be executed in the server, so add the following Spring bean definitions to example-persistent-store.xml:
      <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver">
</property>
<property name="url" value="jdbc:mysql://localhost:3366/persistence">
</property>
<property name="username" value="root"></property>
<property name="password" value="password"></property>
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
  1. Start the Ignite server instance with the Spring config we just added: examples/config/persistentstore/example-persistent-store.xml.
  1. Run the program. It will save the cache entries to our MySQL table:

We created a persistent code to store data to a MySQL table; how about a NoSQL data store? The following section will store data to a NoSQL datastore.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.108.119