---
title: Spring Data Redis(1.0.0.M1)を試す
tags: []
categories: ["Programming", "Java", "org", "springframework", "data", "redis"]
date: 2010-12-18T12:06:30Z
updated: 2010-12-18T15:29:04Z
---

SpringのNoSQL対応プロジェクト[Spring Data][1]のRedisサポート1.0.0.M1版を先日リリースしたので試してみました。
まだMavenレポジトリには登録されていなかったので暫定処置として[ここ][2]からDLして、[ローカルMavenレポジトリにインストール][3]しました。

一応、メモしておくと

    $ cd spring-data-redis-1.0.0.M1\dist
    $ mvn install:install-file -Dfile=spring-data-keyvalue-core-1.0.0.M1.jar -Dsources=spring-data-keyvalue-core-1.0.0.M1-sources.jar -Djavadoc=spring-data-keyvalue-core-1.0.0.M1-javadoc.jar -DgroupId=org.springframework.data -DartifactId=spring-data-keyvalue-core -Dversion=1.0.0.M1 -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true
    $ mvn install:install-file -Dfile=spring-data-redis-1.0.0.M1.jar -Dsources=spring-data-redis-1.0.0.M1-sources.jar -Djavadoc=spring-data-redis-1.0.0.M1-javadoc.jar -DgroupId=org.springframework.data -DartifactId=spring-data-redis -Dversion=1.0.0.M1 -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true


### redisインストール&起動

Cygwinでさくっと

    $ wget http://code.google.com/p/redis/downloads/detail?name=redis-2.0.4.tar.gz
    $ tar xzvf redis-2.0.4.tar.gz
    $ cd redis-2.0.4
    $ make
    $ ./redis-server

### pom.xml

全部必要か分からないけど、pom.xmlはこんな感じ



    <?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/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>am.ik</groupId>
        <artifactId>spring-data-sample</artifactId>
        <packaging>jar</packaging>
        <version>0.1</version>
        <name>spring-data-sample</name>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <spring.version>3.0.5.RELEASE</spring.version>
            <spring.data.version>1.0.0.M1</spring.data.version>
        </properties>
    
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                        <encoding>UTF-8</encoding>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
        <dependencies>
            <!-- Spring -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-tx</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <!-- Spring Data -->
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-keyvalue-core</artifactId>
                <version>${spring.data.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-redis</artifactId>
                <version>${spring.data.version}</version>
            </dependency>
    
            <!-- JRedis -->
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>1.5.0-RC1</version>
            </dependency>
    
            <dependency>
                <groupId>commons-pool</groupId>
                <artifactId>commons-pool</artifactId>
                <version>1.5.5</version>
            </dependency>
    
        </dependencies>
    </project>

`org.springframework.core.serializer.support.SerializingConverter`を使用しており、Springのバージョンは3.0.5以上じゃないと動かない模様。

### applicationContext.xml

Bean定義ファイルにSpringおなじみの`ConnectionFactory`と`Template`を定義。


    <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"
        xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="connectionFactory"
            class="org.springframework.data.keyvalue.redis.connection.jedis.JedisConnectionFactory"
            p:host-name="localhost" p:port="6379" p:pooling="true" />
    
    
        <bean id="redisTemplate"
            class="org.springframework.data.keyvalue.redis.core.RedisTemplate"
            p:connection-factory-ref="connectionFactory" />
    
        <bean id="stringRedisTemplate"
            class="org.springframework.data.keyvalue.redis.core.StringRedisTemplate"
            p:connection-factory-ref="connectionFactory" />
    </beans>

`RedisTemplate`はkeyとvalueの型をジェネリクスで指定する。keyもvalueも`String`の場合は`StringRedisTemplate`を使う。
`RedisTemplate`は汎用シリアライザ/でシリアライザを使い、`StringRedisTemplate`は`String`用の軽いシリアライザ/でシリアライザを使うぽい。

### 使用例

↓前提で

    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

`Operation`を使った例のみ試した。他にも使い方はあるようだ。

#### keyもvalueも`String`の場合

    StringRedisTemplate stringTemplate = (StringRedisTemplate) context.getBean("stringRedisTemplate");

##### 単純な値のset/get

`org.springframework.data.keyvalue.redis.core.ValueOperations`を利用します。

    stringTemplate.getValueOps().set("bar", "zzz");
    stringTemplate.getValueOps().get("bar"); // -> zzz

##### `List`のset/get

`org.springframework.data.keyvalue.redis.core.ListOperations`を利用します。

    stringTemplate.getListOps().leftPush("lst", "xxx");
    stringTemplate.getListOps().leftPush("lst", "yyy");
    stringTemplate.getListOps().leftPush("lst", "zzz");
    stringTemplate.getListOps().rightPush("lst", "111");
    
    stringTemplate.getListOps().range("lst", 0, 1); // -> [zzz, yyy]
    stringTemplate.getListOps().range("lst", 0, -1); // -> [zzz, yyy, xxx, 111]
    
    stringTemplate.getListOps().leftPop("lst"); // -> zzz
    stringTemplate.getListOps().rightPop("lst"); // -> 111
    stringTemplate.getListOps().range("lst", 0, -1); // -> [yyy, xxx]

##### `Hash`のset/get

`org.springframework.data.keyvalue.redis.core.HashOperations`を利用します。

    stringTemplate.getHashOps().set("hsh", "k1", "v1");
    stringTemplate.getHashOps().set("hsh", "k2", "v2");
    stringTemplate.getHashOps().set("hsh", "k2", "v2");
    
    stringTemplate.getHashOps().get("hsh", "k1"); // v1
    stringTemplate.getHashOps().keys("hsh"); // [k1, k2, k3]
    stringTemplate.getHashOps().values("hsh"); // [v1, v2, v3]

`java.util.Map`形式で取得するインタフェースがない?

他にも`SetOperations`とかある。

##### multiSet/Get

一部の`Operation`でサポートされている。

    Map<String, String> vals = new HashMap<String, String>();
    vals.put("k1", "v1");
    vals.put("k2", "v2");
    vals.put("k3", "v3");
    stringTemplate.getValueOps().multiSet(vals);
    stringTemplate.getValueOps().multiGet(Arrays.asList("k1","k2","k3")); // [v1, v2, v3]

##### CAS
一部の`Operation`でサポートされている。

    stringTemplate.getValueOps().setIfAbsent("foo", "xxx"); // 初セットの場合true、セット済みの場合false
    stringTemplate.getValueOps().getAndSet("foo", "aaa"); // xxx
    stringTemplate.getValueOps().get("foo"); // aaa

##### カウンター

    stringTemplate.getValueOps().increment("counter", 1); // 1 (Long型)
    stringTemplate.getValueOps().increment("counter", 1); // 2
    stringTemplate.getValueOps().get("counter"); // 1 (この場合String型)

#### key、valueが任意のオブジェクト
次の`Person`オブジェクトを値に使用します。

##### Person.java

    public class Person implements Serializable {
    
        private static final long serialVersionUID = 92633004015631981L;
    
        private String firstName;
        private String lastName;
    
        private Integer age;
        private Address address;
    
        public Person(String firstName, String lastName, int age, Address address) {
            super();
            this.firstName = firstName;
            this.lastName = lastName;
            this.age = age;
            this.address = address;
        }
    
        // setter/getterは略
    
        // Eclipseの機能(Alt+Shift+S → H)でhashCode/equalsを実装する
        @Override
        public int hashCode() {
            ....
        }
    
        @Override
        public boolean equals(Object obj) {
            ....
        }
    
        @Override
        public String toString() {
            return "Person [firstName=" + firstName + ", lastName=" + lastName
                    + ", age=" + age + ", address=" + address + "]";
        }
    }

##### Address.java

    public class Address implements Serializable {
    
        private static final long serialVersionUID = 4924045450477798779L;
    
        private String street;
    
        private Integer number;
    
        public Address(String street, int number) {
            super();
            this.street = street;
            this.number = number;
        }
    
        // Eclipseの機能(Alt+Shift+S → H)でhashCode/equalsを実装する
        @Override
        public int hashCode() {
            ....
        }
    
        @Override
        public boolean equals(Object obj) {
            ....
        }
    
        @Override
        public String toString() {
            return "Address [street=" + street + ", number=" + number + "]";
        }
    }


汎用テンプレートを使用します

    RedisTemplate<String, Person> template = (RedisTemplate<String, Person>) context.getBean("redisTemplate");

##### 単純な値のset/get

    Person p1 = new Person("Johon", "Smith", 20, new Address("foo", 100));
    Person p2 = new Person("Taro", "Yamada", 25, new Address("aaa", 200));
    
    template.getValueOps().set("p1", p1);
    template.getValueOps().set("p2", p2);
    
    template.getValueOps().get("p1"); // Person [firstName=Johon, lastName=Smith, age=20, address=Address [street=foo, number=100]]
    template.getValueOps().get("p2"); // Person [firstName=Taro, lastName=Yamada, age=25, address=Address [street=aaa, number=200]]

その他`String`の場合と同じ。

ちなみに自分の環境では1プロセスで9回以上操作すると固まる、、、何故だ。。。


  [1]: http://www.springsource.org/spring-data
  [2]: http://www.springsource.com/download/community?project=Spring%20Data125125125
  [3]: http://blog.ik.am/entry/view/id/38/title/Maven2%E3%81%A7%E3%83%AC%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AB%E5%86%85jar%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/
