Middleware/Redis 2019. 3. 1. 14:02

Springboot,redis - Redis repository 간단한사용법!




우선 처음에 조금 헤메긴 했지만, Redis Repository를 사용하려면 기존에 어떠한 Datasource라도 존재를 해야하는 것 같다. 그래서 임의로 인메모리디비인 H2를 dependency하였고, 모든 Datasource는 기본설정으로 두었다. 이렇게 인메모리 디비 데이터소스를 이용함에도 불구하고, 실제로는 Redis에 데이터가 삽입되는 것을 볼수 있다. 이유는 잘모르지만....아시는 분 있으시면 알려주세요...




1
2
3
4
5
6
7
8
9
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
64
65
66
67
68
69
70
71
72
73
74
75
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.brownfield.pss</groupId>
    <artifactId>redis-cluster</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>redis-cluster</name>
    <description>Demo project for Spring Boot</description>
 
    <properties>
        <java.version>1.8</java.version>
    </properties>
 
    <dependencies>
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>
        <!-- H2 -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.json/json -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20160810</version>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
</project>
 
cs


pom.xml이다. 일단 Datasource가 필요하다라는 예외메시지에 H2 인메모리 디비를 dependency했다.


1
2
3
4
5
6
7
8
9
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
64
/**
 * Redis Configuration
 * @author yun-yeoseong
 *
 */
@Configuration
@EnableRedisRepositories
public class RedisConfig {
    
    
    /**
     * Redis Cluster 구성 설정
     */
    @Autowired
    private RedisClusterConfigurationProperties clusterProperties;
    
    /**
     * JedisPool관련 설정
     * @return
     */
    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        return new JedisPoolConfig();
    }
    
    
    /**
     * Redis Cluster 구성 설정
     */
    @Bean
    public RedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
        return new JedisConnectionFactory(new RedisClusterConfiguration(clusterProperties.getNodes()),jedisPoolConfig);
    }
    
    /**
     * RedisTemplate관련 설정
     * 
     * -Thread-safety Bean
     * @param jedisConnectionConfig - RedisTemplate에 설정할 JedisConnectionConfig
     * @return
     */
    @Bean(name="redisTemplate")
    public RedisTemplate redisTemplateConfig(JedisConnectionFactory jedisConnectionConfig) {
        
        RedisTemplate redisTemplate = new RedisTemplate<>();
 
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(jedisConnectionConfig);
        
        return redisTemplate;
        
    }
//    @Bean
//    RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {
//    
//      RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
//      template.setConnectionFactory(connectionFactory);
//      return template;
//    }
    
    
}
 
cs


Redis Config이다. @EnableRedisRepositories 어노테이션을 이용하여 레디스 레포지토리를 이용한다고 명시하였다. 나머지 설정은

이전 포스팅에서 구성했던 Redis Cluster 환경과 동일하게 진행하였다.



1
2
3
4
5
6
7
8
package com.spring.redis;
 
import org.springframework.data.repository.CrudRepository;
 
public interface RedisRepository extends CrudRepository<RedisEntity, Long> {
    public RedisEntity findByFirstname(String firstname);
}
 
cs

RedisRepositry 인터페이스이다. 사용법은 JPA 레포지토리랑 동일한것 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.spring.redis;
 
import java.io.Serializable;
 
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.index.Indexed;
 
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
 
@RedisHash("person")
@Getter
@Setter
@ToString
public class RedisEntity implements Serializable{
    
    private static final long serialVersionUID = 1370692830319429806L;
 
    @Id
    private Long id;
    
//    @Indexed
    private String firstname;
    
//    @Indexed
    private String lastname;
 
    private int age;
 
}
 
cs


Redis 엔티티 설정이다. @RedisHash("person")으로 해당 엔티티가 레디스엔티티임을 명시하였다. 여러글을 읽다가 딱 설명하기 좋은 글이있었다.




RedisEntity라는 엔티티 데이터들을 이후에 무수히 많이 저장이 될것이다. 그래서 이 엔티티들만을 보관하는 하나의 해쉬키 값이 @RedisHash("person")이

되는 것이다. 그리고 이 해쉬 공간에서 각 엔티티들이 person:hash_id 라는 아이디 값을 가지게 된다.(실제로 @Id에 매핑되는 것은 Hash_id) 

이것을 간단히 cli로 보여드리면



사실 key list를 불러오기 위해 " keys * "라는 명령어를 사용할 수 있지만, 이 명령어를 실행시키면 그동안 Redis의 모든 행동은 all stop 됨에 주의하자.


데이터 구조가 이해가 되는가?

이것을 자바의 해쉬 타입으로 지정한다면

HashMap<String,HashMap<String,Person>>의 구조가 되는 것이다. 해쉬의해쉬타입이 된다는 것이 그림에서도 표현이 되있다.



1
2
3
4
5
6
7
8
9
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
package com.spring.redis;
 
import java.util.Arrays;
import java.util.List;
 
import javax.annotation.Resource;
 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.test.context.junit4.SpringRunner;
 
 
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
    
    @Autowired
    private RedisTemplate redisTemplate;
    
    @Autowired
    private RedisRepository repository;
    
//    @Test
//    public void testDataHandling() {
//        
//        redisTemplate.getConnectionFactory().getConnection().info().toString();
//        
//        String key = "yeoseong";
//        String value = "yoon";
//        redisTemplate.opsForValue().set(key, value);
//        String returnValue = (String) redisTemplate.opsForValue().get(key);
//        
//        System.out.println(value);
//    }
    
    @Test
    public void redisRepository() {
        RedisEntity entity = new RedisEntity();
        entity.setFirstname("yeoseong");
        entity.setLastname("yoon");
        entity.setAge(28);
        repository.save(entity);
        RedisEntity findEntity = repository.findByFirstname(entity.getFirstname());
        System.out.println(findEntity.toString());
    }
}
 
cs


posted by 여성게
: