Статьи

Apache Ignite с помощью Spring Data

Spring Data предоставляет унифицированный и простой способ доступа к различным типам хранилищ данных, как к системам реляционных баз данных, так и к хранилищам данных NoSQL. Он находится поверх JPA, добавляя еще один уровень абстракции и определяя стандартный дизайн для поддержки уровня персистентности в контексте Spring.

Apache Ignite IgniteRepository реализует интерфейс Spring Data CrudRepository и расширяет базовые возможности CrudRepository , который в свою очередь поддерживает:

  1. Основные операции CRUD в хранилище для определенного типа.
  2. Доступ к сетке Apache Ignite SQL через Spring Data API.

В репозиториях Spring Data вам нужно только написать интерфейс с методами поиска для запроса объектов. Весь метод CRUD для манипулирования объектами будет доставлен автоматически. Например:

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

В этой статье мы рассмотрим следующие темы:

  • Создайте проект Maven с нуля для использования Spring Data с Apache Ignite Grid.
  • Сохранение нескольких сущностей в кэшах Ignite через среду Spring Data.

Прежде чем мы начнем, давайте рассмотрим предварительные условия проекта в вашей песочнице:

  1. Java JDK 1.8
  2. Зажечь версию 2.0
  3. Версия Apache Maven> 3.0.3

Шаг 1

Давайте сначала настроим песочницу. Создайте проект Maven или клонируйте проект из репозитория GitHub.

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

Шаг 2

Измените файл pom.xml, добавьте следующие зависимости maven:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<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>

Обратите внимание, что зависимость maven h2 является необязательной. Если вы получаете сообщение об ошибке типа «org.h2.result.RowFactory», добавьте зависимость явно.

Модель предметной области

Наш пример доменной модели состоял из двух разных сущностей: породы и собаки.

Ассоциация между породой и собакой — ManyToOne . У одной собаки может быть только одна порода.

Шаг 3

Теперь давайте сопоставим модель предметной области, создав классы Java и снабдив их необходимой мета-информацией. Давайте начнем с класса породы.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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 + '\'' +
                '}';
    }
}

Обратите внимание, что аннотация @QuerySqlField включает поля для запросов SQL.

Создайте другой класс с именем Dog и добавьте в него следующее содержимое.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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 +
                '}';
    }
}

Шаг 4

Теперь давайте создадим репозиторий Spring для всех созданных ранее pojo.

01
02
03
04
05
06
07
08
09
10
11
12
13
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);
}

Необходимо указать аннотацию @RepositoryConfig, чтобы сопоставить хранилище с распределенным кешем. Также у нас есть два метода поиска getDogByName и getDogById для запроса кеша.

Давайте добавим похожий репозиторий для домена Breed следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
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);
}

В приведенном выше интерфейсе BreedRepository мы также используем аннотацию @Query (queryString), которую можно использовать, если конкретный запрос SQL должен быть выполнен в результате вызова метода.

Шаг 5

Давайте создадим класс конфигурации кеша. Создайте класс конфигурации Ignite и отметьте конфигурацию приложения аннотацией @EnableIgniteRepositories, как показано ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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);
    }
}

Обратите внимание, что мы использовали два отдельных CacheConfiguration для кэша Breed и Dog. Также установите схему SQL для кеша.

Шаг 6

Когда все конфигурации и репозитории готовы к использованию, нам нужно зарегистрировать конфигурацию только в контексте приложения Spring.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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(1L);
        collie.setName("collie");
        //save Breed with name collie
        breedRepository.save(1L, 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(1L);
        dina.setBreedid(1L);
        dina.setBirthdate(new Date(System.currentTimeMillis()));
        //Save Dina
        dogRepository.save(2L,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);
        }
 
    }
}

Приведенный выше фрагмент кода очень прост. Сначала мы создаем аннотированный контекст Spring и регистрируем наши репозитории. Далее мы получаем ссылку на наш BreedRepository и DogRepository, чтобы вставить несколько данных. Для запроса данных мы используем базовые операции или методы CRUD, которые автоматически превращаются в запросы Apache Ignite SQL:

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

Шаг 7

Давайте создадим и запустим приложение. Выполните следующую команду.

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

Вы должны найти много сообщений журнала в консоли.

Сообщения журнала подтверждают, что две записи (dina и breed-collie) были сброшены в кэш Ignite и извлечены собаки Dina из кеша. Давайте исследуем кеш через Ignite Visor.

Для сущностей были созданы два разных тайника: Порода и Собака. Если мы просканируем записи в кеше Dog, мы должны найти следующую сущность в нем.

Сущность Дина была сохранена в тайнике с ключом от колли породы.

Если вы хотите узнать больше об Apache Ignite (с использованием JPA, Hibernate или MyBatis), обратитесь к книге « Высокопроизводительные вычисления в памяти с Apache Ignite» .

Ссылка: Apache Ignite с Spring Data от нашего партнера JCG Шамима Буйяна в блоге My workspace .