Comment Spring Data fonctionne avec Redis

Redis (Remote Dictionary Server) est à juste titre considéré comme un vieil homme dans le monde des solutions NoSql. Cet article explique comment Spring Data fonctionne avec. L'idée d'écrire ce post est née car Redis n'est pas tout à fait similaire à la base de données habituelle, il prend en charge des types de données qui ne sont pas pratiques à utiliser pour stocker des objets (le cache ne compte pas) et pour rechercher certains champs. Ici, avec des exemples, je vais essayer de décrire comment Spring Data fonctionne avec lui via les familiers CrudRepository et QueryDSL. Ce n'est pas un exemple de HowTo, dont il existe de nombreux. Qui s'intéresse à l'intérieur va plus loin.

Les exemples seront basés sur un projet simple . Redis monte dans un conteneur docker, une application à démarrage à ressort qui communique également avec lui dans le conteneur. L'application contient un modèle simple, un référentiel, un service et un contrôleur. Vous pouvez toucher tout cela via swagger sur localhost: 8080.

En plus des commandes que le service exécute sur la base de données, je fournirai également un petit pseudo-code qui décrit plus clairement ce qui se passe.



Nous travaillerons avec l'entité étudiante:

@Data
@AllArgsConstructor
@NoArgsConstructor
@RedisHash("Student")
public class Student {
    @Id
    private String id;
    private String name;
    private int age;
}

Ici, il est nécessaire de préciser que l'annotation @RedisHash("Student")indique sous quelle clé toutes les entités seront agrégées.

Essayons de garder le premier étudiant:

curl -X POST "http://localhost:8080/save" -H  "accept: */*" -H  "Content-Type: application/json" -d "{\"id\":\"1\",\"name\":\"Stephen\",\"age\":12}"

3 commandes ont été exécutées:

"DEL" "Student:1"
"HMSET" "Student:1" "_class" "com.odis.redisserviceweb.model.Student" "id" "1" "name" "Stephen" "age" "12"
"SADD" "Student" "1"

, - "DEL" "Student:1", "Student:1". @RedisHash + @Id.

"HMSET" "Student:1" "_class" "com.odis.redisserviceweb.model.Student" "id" "1" "name" "Stephen" "age" "12". "Student:1". -

Map "Student:1";
"Student:1".put("_class", "com.odis.redisserviceweb.model.Student");
"Student:1".put("id", "1");
"Student:1".put("name", "Stephen");
"Student:1".put("age", "12");

- "SADD" "Student" "1" - "Student" "1".

? Redis. - "Student:1", - "Student".

keys * - ( ) :

127.0.0.1:6379> keys *
1) "Student"
2) "Student:1"

, :

127.0.0.1:6379> type "Student"
set
127.0.0.1:6379> type "Student:1"
hash

- ? .

@Id :

curl -X GET "http://localhost:8080/get/1" -H  "accept: */*"

"Student:1" , :

"HGETALL" "Student:1"
1) "_class"
2) "com.odis.redisserviceweb.model.Student"
3) "id"
4) "1"
5) "name"
6) "Stephen"
7) "age"
8) "12"

, , :

curl -X POST "http://localhost:8080/save" -H  "accept: */*" -H  "Content-Type: application/json" -d "{\"id\":\"2\",\"name\":\"Macaulay\",\"age\":40}"
curl -X GET "http://localhost:8080/get" -H  "accept: */*"

3 :

"SMEMBERS" "Student"
1) "1"
2) "2"

"HGETALL" "Student:1"
1) "_class"
2) "com.odis.redisserviceweb.model.Student"
3) "id"
4) "1"
5) "name"
6) "Stephen"
7) "age"
8) "12"
127.0.0.1

"HGETALL" "Student:2"
1) "_class"
2) "com.odis.redisserviceweb.model.Student"
3) "id"
4) "2"
5) "name"
6) "Macaulay"
7) "age"
8) "40"

. - "Student" - , "Student:@Id". , O (N) N - .

:

curl -X DELETE "http://localhost:8080/delete/1" -H  "accept: */*"

:

"HGETALL" "Student:1"
1) "_class"
2) "com.odis.redisserviceweb.model.Student"
3) "id"
4) "1"
5) "name"
6) "Stephen"
7) "age"
8) "12"

"DEL" "Student:1"
(integer) 1

"SREM" "Student" "1"
(integer) 1

"SMEMBERS" "Student:1:idx"
(empty array)

"DEL" "Student:1:idx"
(integer) 0

, Id . "Student" "1".

Student:1:idx. . , . :

List<Student> findAllByName(String name);

:

curl -X POST "http://localhost:8080/save" -H  "accept: */*" -H  "Content-Type: application/json" -d "{\"id\":\"1\",\"name\":\"Stephen\",\"age\":12}"
curl -X GET "http://localhost:8080/get/filter/Stephen" -H  "accept: */*"

, Redis :

"SINTER" "Student:name:Stephen"
(empty array)

"SINTER" - , , - "Student:name:Stephen" .



, , @Id, @Indexed Spring Data , . . Redis . name :

@Data
@AllArgsConstructor
@NoArgsConstructor
@RedisHash("Student")
public class Student {
    @Id
    private String id;
    @Indexed
    private String name;
    private int age;
}

:

curl -X POST "http://localhost:8080/save" -H  "accept: */*" -H  "Content-Type: application/json" -d "{\"id\":\"1\",\"name\":\"Stephen\",\"age\":12}"

:

"DEL" "Student:1"
"HMSET" "Student:1" "_class" "com.odis.redisserviceweb.model.Student" "id" "1" "name" "Stephen" "age" "12"
"SADD" "Student" "1"
"SADD" "Student:name:Stephen" "1"
"SADD" "Student:1:idx" "Student:name:Stephen"

, : "Student:name:Stephen" , , @Indexed . Id . Id Stephen Id . , . - :

Map "Student:1";
"Student:1".put("_class", "com.odis.redisserviceweb.model.Student");
"Student:1".put("id", "1");
"Student:1".put("name", "Stephen");
"Student:1".put("age", "12");

Set "Student";
"Student".add("1");

Set "Student:name:Stephen";
"Student:name:Stephen".add("1");

Set "Student:1:idx";
"Student:1:idx".add("Student:name:Stephen");

, , Redis :

"SINTER" "Student:name:Stephen"
"HGETALL" "Student:1"

Id , . .

SINTER . id .

.

, Spring Data Redis. Spring.



L'inconvénient est que les champs sur lesquels la recherche sera effectuée doivent être marqués @Indexedd'une annotation dès le début. Sinon, les «index» ne seront créés que pour les entités qui sont conservées après l'ajout de cette annotation. Et oui, je comprends que Redis n'est pas la meilleure solution pour de tels besoins, mais si en raison d'une certaine situation, il doit être utilisé, SpringData sera en mesure de le faire très bien.




All Articles