DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Data Engineering
  3. Databases
  4. Apache Ignite With Spring Data

Apache Ignite With Spring Data

Learn how to create a Maven project for using Spring Data with Apache Ignite Grid and how to persist entities into Ignite caches through the Spring Data framework.

Shamim Bhuiyan user avatar by
Shamim Bhuiyan
CORE ·
Jul. 11, 17 · Tutorial
Like (8)
Save
Tweet
Share
17.92K Views

Join the DZone community and get the full member experience.

Join For Free

If you want to learn more about Apache Ignite (using JPA, Hibernate or MyBatis), check out my book.

Spring Data provides a unified and easy way to access the different kinds of persistence stores: both relational database systems and NoSQL data stores. It is on top of JPA, adding another layer of abstraction and defining a standard-based design to support persistence layers in a Spring context.

Image title

Apache Ignite IgniteRepository implements the Spring Data CrudRepository interface and extends the basic capabilities of the CrudRepository, which in turns supports:

  • Basic CRUD operations on a repository for a specific type.

  • Access to the Apache Ignite SQL grid via Spring Data API.

Sprig Data and Ignite

With Spring Data's repositories, you only need to write an interface with finder methods to query the objects. All the CRUD methods for manipulating the objects will be delivered automatically. As an example:

@RepositoryConfig(cacheName = "DogCache")
public interface DogRepository extends IgniteRepository < Dog, Long > {
 List < Dog > getDogByName(String name);
 Dog getDogById(Long id);
}

In this article, we are going to cover the following topics:

  • Create a Maven project from scratch for using Spring Data with Apache Ignite Grid.

  • Persist a few entities into Ignite caches through Spring Data framework.

Before we start, let's cover the prerequisites of the project in your sandbox:

  1. Java JDK 1.8

  2. Ignite version 2.0.

  3. Apache Maven version >3.0.3.

The Apache Ignite book

An updated version of using Spring data with Ignite described in the book The Apache Ignite book. If it got you interested, check out the rest of the book for more helpful information. There is a special 20% discount for the DZone readers, please use the following coupon.

Step 1

Let’s set up the sandbox first. Create a Maven project or clone the project from the GitHub repository.

mvn archetype:create -DgroupId=com.blu.imdg -DartifactId=spring-data

Step 2

Modify the pom.xml and add the following Maven dependencies:

<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-core</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-spring</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-spring-data</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-indexing</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.195</version>
</dependency>

Note that the Maven h2 dependency is optional. If you are getting an error like org.h2.result.RowFactory, then add the dependency explicitly.

The Domain Model

Our example domain model consisted of two different entities: Breed and Dog.

Domain model

The association between Breed and Dog is ManyToOne. One Dog can have only one Breed.

Step 3

Now, let’s map the domain model by creating the Java classes and annotating them with the required meta-information. Let’s start with the Breed class.

package com.blu.imdg.model;

import org.apache.ignite.cache.query.annotations.QuerySqlField;

import java.io.Serializable;

public class Breed implements Serializable {

 @QuerySqlField(index = true)
 private Long id;

 @QuerySqlField(index = true)
 private String name;

 public Long getId() {

  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 @Override
 public String toString() {
  return "Breed{" +
   "id='" + id + '\'' +
   ", name='" + name + '\'' +
   '}';
 }
}

Note that the @QuerySqlField annotation enables the fields for SQL queries.

Create another class named Dog and add the following contents to it:

package com.blu.imdg.model;

import org.apache.ignite.cache.query.annotations.QuerySqlField;

import java.io.Serializable;
import java.sql.Date;

public class Dog implements Serializable {

 @QuerySqlField(index = true)
 private Long id;
 @QuerySqlField(index = true)
 private String name;
 @QuerySqlField(index = true)
 private Long breedid;
 @QuerySqlField(index = true)
 private Date birthdate;

 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public Long getBreedid() {
  return breedid;
 }

 public void setBreedid(Long breedid) {
  this.breedid = breedid;
 }

 public Date getBirthdate() {
  return birthdate;
 }

 public void setBirthdate(Date birthdate) {
  this.birthdate = birthdate;
 }

 @Override
 public String toString() {
  return "Dog{" +
   "id=" + id +
   ", name='" + name + '\'' +
   ", breedid=" + breedid +
   ", birthdate=" + birthdate +
   '}';
 }
}

Step 4

Now, let's create the Spring repository for all the POJOs created before.

package com.blu.imdg.repositories;

import com.blu.imdg.model.Dog;
import org.apache.ignite.springdata.repository.IgniteRepository;
import org.apache.ignite.springdata.repository.config.RepositoryConfig;

import java.util.List;

@RepositoryConfig(cacheName = "DogCache")
public interface DogRepository extends IgniteRepository < Dog, Long > {
 List < Dog > getDogByName(String name);
 Dog getDogById(Long id);
}

The @RepositoryConfig annotation should be specified to map a repository to a distributed cache. Also, we have two finder methods, getDogByName and getDogById, for querying the cache.

Let's add a similar repository for the Breed domain as follows:

package com.blu.imdg.repositories;

import com.blu.imdg.model.Breed;
import org.apache.ignite.springdata.repository.IgniteRepository;
import org.apache.ignite.springdata.repository.config.Query;
import org.apache.ignite.springdata.repository.config.RepositoryConfig;
import org.springframework.data.domain.Pageable;

import java.util.List;

@RepositoryConfig(cacheName = "BreedCache")
public interface BreedRepository extends IgniteRepository < Breed, Long > {

 List < Breed > getAllBreedsByName(String name);

 @Query("SELECT id FROM Breed WHERE id = ?")
 List < Long > getById(long id, Pageable pageable);
}

In the above BreedRepository interface, we also use the @Query(queryString) annotation, which can be used if a concrete SQL query needs to be executed as a result of a method call.

Step 5

Let’s create the cache configuration class. Create an Ignite cache configuration class and mark the application configuration with the @EnableIgniteRepositories annotation, as shown below:

package com.blu.imdg.repositories;

import com.blu.imdg.model.Breed;
import com.blu.imdg.model.Dog;
import org.apache.ignite.Ignite;
import org.apache.ignite.Ignition;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.springdata.repository.config.EnableIgniteRepositories;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableIgniteRepositories
public class SpringAppConfig {
 @Bean
 public Ignite igniteInstance() {
  IgniteConfiguration cfg = new IgniteConfiguration();
  // Setting some custom name for the node.
  cfg.setIgniteInstanceName("springDataNode");
  // Enabling peer-class loading feature.
  cfg.setPeerClassLoadingEnabled(true);
  // Defining and creating a new cache to be used by Ignite Spring Data
  // repository.
  CacheConfiguration ccfgDog = new CacheConfiguration("DogCache");
  CacheConfiguration ccfgBreed = new CacheConfiguration("BreedCache");
  // Setting SQL schema for the cache.
  ccfgBreed.setIndexedTypes(Long.class, Breed.class);
  ccfgDog.setIndexedTypes(Long.class, Dog.class);

  cfg.setCacheConfiguration(new CacheConfiguration[] {
   ccfgDog,
   ccfgBreed
  });

  return Ignition.start(cfg);
 }
}

Note that we have used two separate CacheConfigurations for the Breed and Dog caches. Also, set the SQL schema for the cache.

Step 6

Once all the configurations and repositories are ready to be used, we only need to register the configuration in a Spring application context.

package com.blu.imdg;

import com.blu.imdg.model.Breed;
import com.blu.imdg.model.Dog;
import com.blu.imdg.repositories.BreedRepository;
import com.blu.imdg.repositories.DogRepository;
import com.blu.imdg.repositories.SpringAppConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.sql.Date;
import java.util.List;

/**
 * Hello world!
 *
 */
public class App {
 private static AnnotationConfigApplicationContext ctx;
 private static BreedRepository breedRepository;
 private static DogRepository dogRepository;

 public static void main(String[] args) {
  System.out.println("Spring Data Example!");
  ctx = new AnnotationConfigApplicationContext();
  ctx.register(SpringAppConfig.class);
  ctx.refresh();

  breedRepository = ctx.getBean(BreedRepository.class);
  dogRepository = ctx.getBean(DogRepository.class);

  //fill the repository with data and Save
  Breed collie = new Breed();
  collie.setId(1 L);
  collie.setName("collie");
  //save Breed with name collie
  breedRepository.save(1 L, collie);

  System.out.println("Add one breed in the repository!");
  // Query the breed
  List < Breed > getAllBreeds = breedRepository.getAllBreedsByName("collie");

  for (Breed breed: getAllBreeds) {
   System.out.println("Breed:" + breed);
  }
  //Add some dogs
  Dog dina = new Dog();
  dina.setName("dina");
  dina.setId(1 L);
  dina.setBreedid(1 L);
  dina.setBirthdate(new Date(System.currentTimeMillis()));
  //Save Dina
  dogRepository.save(2 L, dina);
  System.out.println("Dog dina save into the cache!");
  //Query the Dog Dina
  List < Dog > dogs = dogRepository.getDogByName("dina");
  for (Dog dog: dogs) {
   System.out.println("Dog:" + dog);
  }

 }
}

The above code snippet is very straightforward. First, we create a Spring annotated context and register our repositories. Next, we get the reference to our BreedRepository and DogRepository to insert a few data. To query the data we use basic CRUD operations or methods that will be automatically turned into Apache Ignite SQL queries:

List < Dog > dogs = dogRepository.getDogByName("dina");
for (Dog dog: dogs) {
 System.out.println("Dog:" + dog);
}

Step 7

Let’s build and run the application. Execute the following command:

mvn clean install
mvn exec:java -Dexec.mainClass=com.blu.imdg.App

You should find a lot of log messages in the console.:

Log messages

The log messages confirm that two entries (dina and breed-collie) have been flushed into the Ignite cache and retrieved the dog Dina from the cache. Let’s explore the cache through Ignite Visor.

Caches

Two different caches have been created for the entities: Breed and Dog. If we scan the cache entries of the Dog cache, we should find the following entity on it.

Cache entries

Entity Dina has been persisted into the cache with the key of the Breed Collie.

If you want to learn more about Apache Ignite (using JPA, Hibernate or MyBatis), check out my book.

Spring Data Apache Ignite Spring Framework Data (computing)

Published at DZone with permission of Shamim Bhuiyan. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Bye-Bye, Regular Dev [Comic]
  • Stream Processing vs. Batch Processing: What to Know
  • Quick Pattern-Matching Queries in PostgreSQL and YugabyteDB
  • Mind Map Reuse in Software Groups

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: