SpringのNoSQL対応プロジェクトSpring DataのRedisサポート1.0.0.M1版を先日リリースしたので試してみました。 まだMavenレポジトリには登録されていなかったので暫定処置としてここからDLして、ローカルMavenレポジトリにインストールしました。
一応、メモしておくと
$ 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回以上操作すると固まる、、、何故だ。。。