Contactez-nous

Utilisation de `RedisRepository` et `RedisTemplate`

Apprenez à utiliser RedisRepository pour une approche objet simple et RedisTemplate pour un accès direct et flexible aux structures de données Redis dans Spring Boot.

Deux approches pour interagir avec Redis

Une fois Spring Data Redis configuré dans votre application Spring Boot, vous disposez de deux principaux moyens d'interagir avec votre serveur Redis :

  1. RedisRepository : Une approche de plus haut niveau, alignée sur le pattern Repository de Spring Data, idéale pour stocker et récupérer des objets Java simples mappés sur des Hashes Redis.
  2. RedisTemplate / StringRedisTemplate : Une approche de plus bas niveau, offrant un accès direct et complet à toutes les commandes et structures de données Redis (Strings, Lists, Sets, Hashes, etc.).

Le choix entre ces deux approches dépend de la complexité de vos besoins et du type d'interaction que vous souhaitez avoir avec Redis.

`RedisRepository` : L'approche objet simple

Similaire à JpaRepository ou MongoRepository, RedisRepository permet de définir une interface pour gérer la persistance d'une entité spécifique dans Redis. Par défaut, Spring Data Redis mappe les objets gérés par un RedisRepository à des Hashes Redis.

1. Définir l'entité : Annotez votre classe avec @RedisHash pour indiquer qu'elle doit être stockée dans Redis. Utilisez @Id pour marquer le champ qui servira d'identifiant (qui fera partie de la clé Redis).

import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.index.Indexed;
import java.io.Serializable; // Important pour certains sérialiseurs

@RedisHash("persons") // Définit le préfixe du keyspace (ex: keyspace:id)
public class Person implements Serializable { // Implémenter Serializable est souvent requis

    @Id 
    private String id; // L'ID sera utilisé dans la clé Redis
    
    @Indexed // Permet les requêtes dérivées sur ce champ
    private String firstname;
    private String lastname;
    private int age;

    // Constructeur, Getters, Setters...
    public Person(String id, String firstname, String lastname, int age) {
        this.id = id;
        this.firstname = firstname;
        this.lastname = lastname;
        this.age = age;
    }
    // ...
}

L'annotation @Indexed sur un champ permet à Spring Data Redis de maintenir des index secondaires (via des Sets Redis) pour supporter les méthodes de requête dérivées sur ce champ.

2. Créer l'interface Repository : Etendez CrudRepository.

import org.springframework.data.repository.CrudRepository;
import java.util.List;

public interface PersonRepository extends CrudRepository {
    // Méthodes CRUD héritées (save, findById, findAll, delete...)
    
    // Méthodes de requête dérivées possibles grâce à @Indexed
    List findByFirstname(String firstname);
    List findByAgeGreaterThan(int age);
}

3. Activer les Repositories Redis : Ajoutez @EnableRedisRepositories à une classe de configuration (souvent la classe principale) pour activer la détection et la création des beans Repository.

@SpringBootApplication
@EnableRedisRepositories // Active les repositories Redis
public class MyApplication {
    // ...
}

4. Utilisation : Injectez et utilisez le repository comme n'importe quel autre repository Spring Data.

@Autowired
private PersonRepository personRepository;

public void testRepository() {
    Person alice = new Person("id-alice", "Alice", "Smith", 30);
    personRepository.save(alice);

    Optional found = personRepository.findById("id-alice");
    found.ifPresent(p -> System.out.println("Trouvé: " + p.getFirstname()));

    List thirties = personRepository.findByAgeGreaterThan(29);
    System.out.println("Personnes de 30 ans ou plus: " + thirties.size());
}

Limitations : RedisRepository est principalement conçu pour les opérations CRUD sur des objets mappés à des Hashes. Il n'offre pas d'accès direct aux autres types de données Redis (Lists, Sets, etc.) ni un contrôle fin sur les clés ou les expirations (bien que @TimeToLive soit supporté sur l'entité).

`RedisTemplate`/`StringRedisTemplate` : Accès direct et flexibilité

Pour un contrôle complet sur toutes les commandes Redis et pour travailler avec toutes les structures de données, vous utiliserez RedisTemplate ou sa spécialisation pratique StringRedisTemplate.

  • StringRedisTemplate : Optimisé pour le cas le plus courant où les clés et les valeurs sont des chaînes de caractères. Il est auto-configuré par Spring Boot et utilise des sérialiseurs de chaînes (StringRedisSerializer). C'est souvent le plus simple à utiliser pour les interactions basiques.
  • RedisTemplate : Plus générique, permet de stocker des objets Java complexes. Point crucial : sa configuration par défaut utilise la sérialisation Java (JdkSerializationRedisSerializer), qui est généralement déconseillée. Il est fortement recommandé de le reconfigurer pour utiliser un sérialiseur JSON comme GenericJackson2JsonRedisSerializer ou Jackson2JsonRedisSerializer pour une meilleure interopérabilité, sécurité et lisibilité des données dans Redis. (Voir la configuration dans la section précédente).

Injection : Injectez le template approprié dans vos composants.

@Autowired
private StringRedisTemplate stringRedisTemplate;

@Autowired // Injecter le bean configuré avec JSON si nécessaire
private RedisTemplate redisTemplate;

Opérations avec `RedisTemplate` (Illustrations)

RedisTemplate fournit des interfaces "helper" pour accéder aux opérations spécifiques à chaque type de données Redis :

  • opsForValue() : Pour les opérations sur les Strings (équivalent des commandes SET, GET, INCR, etc.).
  • opsForList() : Pour les opérations sur les Listes (LPUSH, RPOP, LRANGE, etc.).
  • opsForSet() : Pour les opérations sur les Sets (SADD, SMEMBERS, SISMEMBER, etc.).
  • opsForZSet() : Pour les opérations sur les Sorted Sets.
  • opsForHash() : Pour les opérations sur les Hashes (HSET, HGET, HGETALL, etc.).

Exemples avec `StringRedisTemplate` (donc ValueOperations) :

public void exampleStringOps() {
    ValueOperations valueOps = stringRedisTemplate.opsForValue();
    
    // SET simple
    valueOps.set("user:1:name", "Alice");
    
    // GET
    String name = valueOps.get("user:1:name"); // name = "Alice"
    System.out.println("Nom récupéré: " + name);

    // SET avec expiration
    valueOps.set("session:xyz", "user-data", Duration.ofMinutes(30));

    // INCR (compteur)
    Long counter = valueOps.increment("page:views");
    System.out.println("Vues: " + counter);
    
    // DELETE
    // stringRedisTemplate.delete("user:1:name");
}

Exemples avec `RedisTemplate` (configuré JSON) :

public void exampleObjectOps() {
    // Opérations sur les listes
    ListOperations listOps = redisTemplate.opsForList();
    String taskListKey = "tasks:user1";
    listOps.leftPush(taskListKey, new Task("T1", "Faire les courses"));
    listOps.leftPush(taskListKey, new Task("T2", "Payer les factures"));
    Task latestTask = (Task) listOps.leftPop(taskListKey);
    System.out.println("Dernière tâche: " + latestTask.getDescription());

    // Opérations sur les Hashes (similaire à @RedisHash mais direct)
    HashOperations hashOps = redisTemplate.opsForHash();
    String productKey = "product:101";
    hashOps.put(productKey, "name", "Laptop X");
    hashOps.put(productKey, "price", 1200.50);
    Map productMap = hashOps.entries(productKey);
    System.out.println("Produit: " + productMap);
}

// Classe Task (doit être sérialisable en JSON)
class Task { 
    private String id; private String description; 
    // Constructeur, Getters (pour Jackson)
    public Task() {}
    public Task(String id, String d) {this.id=id; this.description=d;}
    public String getId(){return id;} public String getDescription(){return description;}
}

`RedisRepository` vs `RedisTemplate` : Quand utiliser quoi ?

  • Utilisez RedisRepository lorsque :
    • Vous voulez une abstraction de haut niveau pour des opérations CRUD sur des objets simples.
    • Vos objets peuvent être naturellement mappés à des Hashes Redis.
    • Vous souhaitez bénéficier des méthodes de requête dérivées pour des recherches simples basées sur des index.
    • La simplicité et la rapidité de développement pour des cas d'usage objet/hash sont prioritaires.
  • Utilisez RedisTemplate / StringRedisTemplate lorsque :
    • Vous avez besoin d'interagir avec des types de données Redis autres que les Hashes (Strings, Lists, Sets, Sorted Sets...).
    • Vous avez besoin d'un contrôle fin sur les clés Redis, les expirations (TTL), ou des commandes Redis spécifiques (INCR, PUBLISH, transactions Redis, scripts Lua...).
    • Vous devez interagir avec des données dans Redis qui n'ont pas été stockées via RedisRepository.
    • Vous privilégiez la flexibilité et l'accès complet à la puissance de Redis par rapport à l'abstraction objet.
    • Vous devez implémenter une logique de cache personnalisée.

Il est tout à fait courant d'utiliser les deux approches au sein de la même application Spring Boot. Vous pouvez utiliser RedisRepository pour gérer la persistance simple de certaines entités et RedisTemplate pour des opérations plus spécifiques, la mise en cache ou la gestion de compteurs.

Conclusion : Choisir le bon outil pour le bon usage

Spring Data Redis offre deux niveaux d'interaction avec Redis : l'abstraction de haut niveau RedisRepository, idéale pour le CRUD objet-hash simple, et l'accès direct et flexible via RedisTemplate / StringRedisTemplate pour exploiter toutes les capacités de Redis. Comprendre les forces et les limitations de chaque approche vous permet de choisir l'outil le plus approprié pour chaque tâche, optimisant ainsi votre utilisation de Redis dans vos applications Spring Boot.