web-dev-qa-db-fra.com

Spring Cacheable vs CachePut?

@CachePut or @Cacheable(value = "CustomerCache", key = "#id")
public Customer updateCustomer(Customer customer) {
   sysout("i am inside updateCustomer");
    ....
    return customer;
}

J'ai trouvé la documentation ci-dessous sous CachePut code source

L'annotation CachePut n'entraîne pas l'omission de la méthode cible, mais provoque toujours l'appel de la méthode et son résultat dans le cache.

Est-ce à dire si j'utilise @Cacheable, la méthode updateCustomer ne sera exécutée qu'une seule fois et le résultat sera mis à jour dans le cache. Les appels suivants à updateCustomer n'exécuteront pas updateCustomer, il mettra simplement à jour le cache.

En cas de @CachePut, updateCustomer sera exécutée à chaque appel et le résultat sera mis à jour dans le cache.

Ma compréhension est-elle correcte?

20
M Sach

Oui.

J'ai même fait un test pour être sûr:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CacheableTest.CacheConfigurations.class)
public class CacheableTest {

    public static class Customer {

        final private String id;
        final private String name;

        public Customer(String id, String name) {
            this.id = id;
            this.name = name;
        }

        public String getId() {
            return id;
        }

        public String getName() {
            return name;
        }

    }

    final public static AtomicInteger cacheableCalled = new AtomicInteger(0);
    final public static AtomicInteger cachePutCalled = new AtomicInteger(0);

    public static class CustomerCachedService {


        @Cacheable("CustomerCache")
        public Customer cacheable(String v) {
            cacheableCalled.incrementAndGet();
            return new Customer(v, "Cacheable " + v);
        }

        @CachePut("CustomerCache")
        public Customer cachePut(String b) {
            cachePutCalled.incrementAndGet();
            return new Customer(b, "Cache put " + b);
        }

    }

    @Configuration
    @EnableCaching()
    public static class CacheConfigurations {

        @Bean
        public CustomerCachedService customerCachedService() {
            return new CustomerCachedService();
        }

        @Bean
        public CacheManager cacheManager() {
            return new GuavaCacheManager("CustomerCache");
        }

    }

    @Autowired
    public CustomerCachedService cachedService;

    @Test
    public void testCacheable() {
        for(int i = 0; i < 1000; i++) {
            cachedService.cacheable("A");
        }
        Assert.assertEquals(cacheableCalled.get(), 1);
    }

    @Test
    public void testCachePut() {
        for(int i = 0; i < 1000; i++) {
            cachedService.cachePut("B");
        }
        Assert.assertEquals(cachePutCalled.get(), 1000);
    }

}
15
mavarazy

@CachePut laisse toujours la méthode s'exécuter. Il est généralement utilisé si vous souhaitez que votre cache soit mis à jour avec le résultat de l'exécution de la méthode.
Exemple: lorsque vous souhaitez mettre à jour des données périmées qui sont mises en cache, au lieu de faire exploser complètement le cache.

@Cacheable ne sera exécuté qu'une seule fois pour la clé de cache donnée et les requêtes suivantes n'exécuteront pas la méthode, jusqu'à ce que le cache expire ou soit vidé.

13
minion

Oui, vous avez absolument raison.

@Cacheput et @Cacheable sont utilisés conjointement.

@Cacheable ne mettra pas à jour le cache à chaque appel. Afin de supprimer les données périmées, il doit exister un service utilisant @Cacheput qui efface les données périmées.

La réponse ci-dessous s'adresse à ceux qui utilisent la mise en cache de goyave pour créer le cache. En utilisant la mise en cache de goyave, l'intervalle de temps qui est appliqué videra le cache après une certaine période de temps, ce qui n'est pas le cas avec @Cacheput. @Cacheput ne mettra à jour que les valeurs périmées et appelle donc la méthode à chaque fois pour mettre à jour le cache.

J'espère que ma réponse éclaircit votre question.

0
Somil Aseeja