Support of Redis for Spring Data

CAST supports Redis via its com.castsoftware.nosqljavaexternal link extension. Details about how this support is provided for Java with Spring Data source code is discussed below.

Supported Libraries

Library Version Supported
RedisConnectionFactory Up to: 2.7.7
RedisTemplate Up to: 2.7.7
StringRedisTemplate Up to: 2.7.7
LettuceConnectionFactory Up to: 2.7.7
JedisConnectionFactory Up to: 2.7.7
CrudRepository * Up to: 2.7.7
JpaRepository * Up to: 2.7.7

CrudRepository and JpaRepository are supported only if the repository is created using @RedisHash domain.

Supported Operations

  • Operation
  • Methods Supported
  • Insert
    org.springframework.data.redis.core.ValueOperations
    • org.springframework.data.redis.core.ValueOperations.set
    • org.springframework.data.redis.core.ValueOperations.multiSet
    • org.springframework.data.redis.core.ValueOperations.multiSetIfAbsent
    • org.springframework.data.redis.core.ValueOperations.setIfAbsent
    • org.springframework.data.redis.core.ValueOperations.append
    org.springframework.data.redis.core.ListOperations
    • org.springframework.data.redis.core.ListOperations.leftPush
    • org.springframework.data.redis.core.ListOperations.leftPushAll
    • org.springframework.data.redis.core.ListOperations.rightPush 
    • org.springframework.data.redis.core.ListOperations.rightPushAll
    • org.springframework.data.redis.core.ListOperations.set
    org.springframework.data.redis.core.HashOperations
    • org.springframework.data.redis.core.HashOperations.putAll
    • org.springframework.data.redis.core.HashOperations.put
    • org.springframework.data.redis.core.HashOperations.putIfAbsent
    • org.springframework.data.redis.core.SetOperations.add
    • org.springframework.data.repository.CrudRepository.save
    • org.springframework.data.repository.CrudRepository.saveAll
    • org.springframework.data.jpa.repository.JpaRepository.save 
    • org.springframework.data.jpa.repository.JpaRepository.saveAll
    • org.springframework.data.jpa.repository.JpaRepository.saveAndFlush
    Select
    org.springframework.data.redis.core.ValueOperations
    • org.springframework.data.redis.core.ValueOperations.get
    • org.springframework.data.redis.core.ValueOperations.multiGet
    • org.springframework.data.redis.core.ValueOperations.size
    • org.springframework.data.redis.core.ValueOperations.bitField
    • org.springframework.data.redis.core.ValueOperations.getAndDelete
    • org.springframework.data.redis.core.ValueOperations.getAndSet
    org.springframework.data.redis.core.ListOperations
    • org.springframework.data.redis.core.ListOperations.range
    • org.springframework.data.redis.core.ListOperations.size
    • org.springframework.data.redis.core.ListOperations.index
    • org.springframework.data.redis.core.ListOperations.indexOf
    • org.springframework.data.redis.core.ListOperations.lastIndexOf
    org.springframework.data.redis.core.HashOperations
    • org.springframework.data.redis.core.HashOperations.hasKey
    • org.springframework.data.redis.core.HashOperations.get
    • org.springframework.data.redis.core.HashOperations.multiGet
    • org.springframework.data.redis.core.HashOperations.keys
    • org.springframework.data.redis.core.HashOperations.values
    • org.springframework.data.redis.core.HashOperations.lengthOfValue
    • org.springframework.data.redis.core.HashOperations.size
    • org.springframework.data.redis.core.HashOperations.entries
    • org.springframework.data.redis.core.HashOperations.randomEntries
    • org.springframework.data.redis.core.HashOperations.randomEntry
    • org.springframework.data.redis.core.HashOperations.randomKey
    • org.springframework.data.redis.core.HashOperations.randomKeys
    • org.springframework.data.redis.core.HashOperations.scan
    org.springframework.data.redis.core.SetOperations
    • org.springframework.data.redis.core.SetOperations.size
    • org.springframework.data.redis.core.SetOperations.isMember
    • org.springframework.data.redis.core.SetOperations.members
    org.springframework.data.repository.CrudRepository
    • org.springframework.data.repository.CrudRepository.findAll
    • org.springframework.data.repository.CrudRepository.count
    • org.springframework.data.repository.CrudRepository.findById
    • org.springframework.data.repository.CrudRepository.findAllById
    • org.springframework.data.repository.CrudRepository.existsById
    org.springframework.data.jpa.repository.JpaRepository
    • org.springframework.data.jpa.repository.JpaRepository.count
    • org.springframework.data.jpa.repository.JpaRepository.findAll
    • org.springframework.data.jpa.repository.JpaRepository.findAllById
    • org.springframework.data.jpa.repository.JpaRepository.exists
    • org.springframework.data.jpa.repository.JpaRepository.findOne
    • org.springframework.data.jpa.repository.JpaRepository.findById
    • org.springframework.data.jpa.repository.JpaRepository.existsById
    • org.springframework.data.repository.PagingAndSortingRepository.findAll
    Delete
    org.springframework.data.redis.core.ListOperations
    • org.springframework.data.redis.core.ListOperations.remove
    • org.springframework.data.redis.core.ListOperations.rightPop
    • org.springframework.data.redis.core.ListOperations.leftPop
    org.springframework.data.repository.CrudRepository
    • org.springframework.data.repository.CrudRepository.deleteAll
    • org.springframework.data.repository.CrudRepository.deleteById
    • org.springframework.data.repository.CrudRepository.delete
    org.springframework.data.jpa.repository.JpaRepository
    • org.springframework.data.jpa.repository.JpaRepository.deleteInBatch
    • org.springframework.data.jpa.repository.JpaRepository.deleteAllInBatch
    • org.springframework.data.jpa.repository.JpaRepository.delete
    • org.springframework.data.jpa.repository.JpaRepository.deleteAll
    • org.springframework.data.jpa.repository.JpaRepository.deleteAllById
    • org.springframework.data.jpa.repository.JpaRepository.deleteById
    • org.springframework.data.redis.core.HashOperations.delete
    • org.springframework.data.redis.core.SetOperations.remove
    • org.springframework.data.redis.core.SetOperations.pop
    • org.springframework.data.redis.core.ValueOperations.getAndDelete
    • org.springframework.data.redis.core.RedisTemplate.delete
    Update
    org.springframework.data.jpa.repository.JpaRepository
    • org.springframework.data.jpa.repository.JpaRepository.deleteInBatch
    • org.springframework.data.jpa.repository.JpaRepository.deleteAllInBatch
    • org.springframework.data.jpa.repository.JpaRepository.delete
    • org.springframework.data.jpa.repository.JpaRepository.deleteAll
    • org.springframework.data.jpa.repository.JpaRepository.deleteAllById
    • org.springframework.data.jpa.repository.JpaRepository.deleteById
    org.springframework.data.redis.core.ValueOperations
    • org.springframework.data.redis.core.ValueOperations.increment
    • org.springframework.data.redis.core.ValueOperations.decrement
    • org.springframework.data.redis.core.ValueOperations.getAndSet
    • org.springframework.data.redis.core.ValueOperations.setIfPresent
    • org.springframework.data.redis.core.ValueOperations.getAndSet
    org.springframework.data.redis.core.ListOperations
    • org.springframework.data.redis.core.ListOperations.trim
    • org.springframework.data.redis.core.ListOperations.leftPushIfPresent
    • org.springframework.data.redis.core.ListOperations.rightPushIfPresent
    • org.springframework.data.redis.core.HashOperations.increment

    Objects

  • Icon
  • Description
  • Java Redis Connection
  • Java Redis Collection
    Java unknown Redis Connection
    Java Unknown Redis Collection
    Link type When is this created? Methods Supported
    parentLink
  • Between Redis connection object and Redis collection object
  • -
    useLink
  • Between the caller Java method object and Redis collection object
    • multiGet
    • get
    • keys
    • entries
    • findAllById
    • findAll
    useSelectLink
  • Between the caller Java method object and Redis collection object
    • multiGet
    • get
    • keys
    • entries
    • findAllById
    • findAll
    useInsertLink
  • Between the caller Java method object and Redis collection object
    •  set
    •  put
    •  putAll
    •  add
    •  leftpush
    • save
    • saveAll
  • useDeleteLink
  • Between the caller Java method object and Redis collection object
    • delete
    • remove
    • deleteById
    • deleteAll
    useUpdateLink
  • Between the caller Java method object and Redis collection object
    • increment
    • decrement

    What results can you expect?

    Some example scenarios are shown below:

    Redis Connections and Collections

    @Autowired
    private ServiceConfigResource serviceConfigResource;
    
    RedisConnectionFactory switchRedisMaster() {
             return getRedisConnectionFactory(serviceConfigResource.getSwitchRedisMaster(), serviceConfigResource.getDisRedisPort());
    }
    

    Java based configurations

    @Configuration
    @RefreshScope
    @Getter
    public class ServiceConfigResource {
    
          @Value("${disredis.host.disRedisHost1}")
             private String switchRedisMaster;
    
          @Value("${disredis.host.disRedisHost2}")
             private String switchRedisSlave1;
    
             @Value("${disredis.host.disRedisHost3}")
             private String switchRedisSlave2;
    
            @Value("${disredis.port.disRedisPort1}")
          private int disRedisPort; 
    
             @Value("${useRoomSharedUsedTable}")
            private int useRoomSharedUsedTable;
    
    }
    

    Xml based configurations

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:p="http://www.springframework.org/schema/p"
      xmlns:redis="http://www.springframework.org/schema/redis"
      xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis.xsd
            ">
        
    <!-- Jedis Connection -->    
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
       p:host-name="localhost" p:port="6379" />
      
    <!-- Redis Template -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <property name="valueSerializer">
            <bean id="redisJsonSerializer" class="org.springframework.data.redis.serializer.JacksonJsonRedisSerializer">
                <constructor-arg type="java.lang.Class" value="redis.User"/>
            </bean>   
        </property>
    </bean>
    
    <bean class="redis.UserRepository"/>
    
    </beans>
    

    Lettuce

     public ReactiveRedisConnectionFactory build() {
        LettuceClientConfiguration clientConfig;
        LettuceClientConfiguration.LettuceClientConfigurationBuilder builder =
            LettuceClientConfiguration.builder();
        if (ssl) {
          builder.commandTimeout(Duration.ofSeconds(timeout)).useSsl();
        }
        clientConfig = builder.build();
    
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        configuration.setHostName(host);
        configuration.setPassword(password);
        configuration.setPort(port);
        return new LettuceConnectionFactory(configuration, clientConfig);
    

    RedisHash Domain 

    /*
     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */
    package io.project.app.domain;
    
    import java.io.Serializable;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    import lombok.NoArgsConstructor;
    import lombok.ToString;
    import org.springframework.data.redis.core.RedisHash;
    
    /
     *
     * @author armena
     */
    @RedisHash
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @ToString
    @EqualsAndHashCode
    public class SearchData implements Serializable{
        
        private String id;   //unique id
        private String key; //key for search
        private String title;
        private String content;
        
    }
    

    Redis Repo Creation using CrudRepository

    /*
     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */
    package io.project.app.repositories;
    
    import io.project.app.domain.SearchData;
    import org.springframework.data.repository.CrudRepository;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Repository;
    
    /
     *
     * @author armena
     */
    @Repository
    @Component
    public interface SearchRepository extends CrudRepository<SearchData, String>{
        
        public SearchRepository findByTitle(String title);
        
    }
    

    Insert Operation

    @Bean(name = "switch_redis_master")
        <T> RedisTemplate<String, T> switchMasterRedis() {
            RedisTemplate template = new RedisTemplate<>();
            FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
            template.setConnectionFactory(switchRedisMaster());
            template.setKeySerializer(new StringRedisSerializer());
            template.setValueSerializer(fastJsonRedisSerializer);
            return template;
        }
    
    @Autowired
    @Qualifier("switch_redis_master")
    private RedisTemplate<String, Integer> redisTemplate;
    
    
    private boolean invokeFrequencyValidate(String agentCode, Date checkInDate, Date checkOutDate) {
            int openingHotelNum = hotelService.getOpeningHotelNum();
            Date currentDate = new Date();
            // 16-90
            if (AbstractDateUtils.isAfter(checkInDate, AbstractDateUtils.getDeltaDateByDays(currentDate, 15))) {
                Integer count = redisTemplate.opsForValue().get(agentCode + "_" + SIXTEEN_TO_NINETY);
                if (count == null) {
                    redisTemplate.opsForValue().set(agentCode + "_" + SIXTEEN_TO_NINETY, 1, TIME_PERIOD_THREE, TimeUnit.MINUTES);
                    return true;
                }
                if (count >= maxQueryBase + openingHotelNum / FIFTEEN_OUTER_DIVIDED) {
                    return false;
                }
                return true;
            }
    

    CrudRepository Insert Operation

      @Autowired
        private SearchRepository searchRepository;
    
        public SearchData save(SearchData googleSearch) {        
            return searchRepository.save(googleSearch);
        }
    

    Select Operation

    private List<RoomShareUsedCountEntity> calculateRoomShareUsedCountWithType(StandardRoomWithTypeRequest standardRoomWithTypeRequest) {
            List<String> validDateList = calculateAllKeyDate(standardRoomWithTypeRequest.getCheckInDate(), standardRoomWithTypeRequest.getCheckOutDate());
            List<String> fullKey = Lists.newArrayList();
    
            List<UsedShareRoomCount> allUsedShareRoomCountList = Lists.newArrayList();
            for (String key : fullKey) {
                List<UsedShareRoomCount> value = (List<UsedShareRoomCount>) usedShareRoomCountSlaveRedisTemplate.opsForValue().get(key);
            }
            if (CollectionUtils.isEmpty(allUsedShareRoomCountList)) {
                return Lists.newArrayList();
            }
            return convert2RoomShareUsedCountEntityFromUsedShareCount(allUsedShareRoomCountList);
        }
    

    CrudRepository Select Operation

      @Autowired
        private SearchRepository searchRepository;
    
        public Optional<SearchData> find(String id) {
           return searchRepository.findById(id);
        }
    

    Update Operation

    private boolean invokeFrequencyValidate(String agentCode, Date checkInDate, Date checkOutDate) {
    
            int openingHotelNum = hotelService.getOpeningHotelNum();
            Date currentDate = new Date();
            // 16-90
            if (AbstractDateUtils.isAfter(checkInDate, AbstractDateUtils.getDeltaDateByDays(currentDate, 15))) {
                Integer count = redisTemplate.opsForValue().get(agentCode + "_" + SIXTEEN_TO_NINETY);
                if (count == null) {
                    redisTemplate.opsForValue().set(agentCode + "_" + SIXTEEN_TO_NINETY, 1, TIME_PERIOD_THREE, TimeUnit.MINUTES);
                    return true;
                }
                if (count >= maxQueryBase + openingHotelNum / FIFTEEN_OUTER_DIVIDED) {
                    return false;
                }
                redisTemplate.opsForValue().increment(agentCode + "_" + SIXTEEN_TO_NINETY, 1);
                return true;
            }
    

    Delete Operation

    public void delete(String key) {
            template.opsForValue().getOperations().delete(key);
        }
    

    CrudRepository Delete Operation

      @Autowired
        private SearchRepository searchRepository;
    
        public Optional<SearchData> delete(String id) {
            return searchRepository.deleteById(id);
        }
    

    Known Limitations

    • Unknown Redis connection/collection objects are created in case of unresolved names.