コンテキスト: Spring data cassandra official 1.0.2.RELEASE from Maven Central repo、CQL3、cassandra 2.0、datastax driver 2.0.4
背景: cassandra blob データ型は Java ByteBuffer にマップされます。
以下のサンプル コードは、同等の挿入の隣にある select を使用して正しいバイトを取得しないことを示しています。実際に取得されたデータには、実際には行全体のシリアル化のように見える多数のガベージ バイトがプレフィックスとして付けられます。Cassandra 1.2 に関連するこの古い投稿では、ByteBuffer.remaining() の長さの ByteBuffer.arrayOffset() から開始する必要があるかもしれないと示唆されていましたが、arrayOffset の値は実際には 0 です。
spring-data-cassandra 2.0.0 を発見しました。スナップショットですが、CassandraOperations API は大きく異なり、そのパッケージ名も org.springdata... 対 org.springframework... です。
これを修正するための助けは大歓迎です。
それまでの間、テキスト データ型の列との間でバイナリ データを Base64 でエンコード/デコードする必要があるようです。
--- これが私が使用する単純なテーブル CQL メタデータです -------------
CREATE TABLE person (
id text,
age int,
name text,
pict blob,
PRIMARY KEY (id)
) ;
--- CQL テーブルにマップされた単純なデータ オブジェクトに従います ---
package org.spring.cassandra.example;
import java.nio.ByteBuffer;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;
@Table
public class Person {
@PrimaryKey
private String id;
private int age;
private String name;
private ByteBuffer pict;
public Person(String id, int age, String name, ByteBuffer pict) {
this.id = id; this.name = name; this.age = age; this.pict = pict;
}
public String getId() { return id; }
public String getName() { return name; }
public int getAge() { return age; }
public ByteBuffer getPict() { return pict; }
}
}
--- そして、単純に人物オブジェクトを挿入して取得する単純な Java アプリケーション コード --
package org.spring.cassandra.example;
import java.nio.ByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.cassandra.core.CassandraOperations;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;
public class CassandraApp {
private static final Logger logger = LoggerFactory
.getLogger(CassandraApp.class);
public static String hexDump(ByteBuffer bb) {
char[] hexArray = "0123456789ABCDEF".toCharArray();
bb.rewind();
char[] hexChars = new char[bb.limit() * 2];
for ( int j = 0; j < bb.limit(); j++ ) {
int v = bb.get() & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
bb.rewind();
return new String(hexChars);
}
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app-context.xml");
try {
CassandraOperations cassandraOps = applicationContext.getBean(
"cassandraTemplate", CassandraOperations.class);
cassandraOps.truncate("person");
// prepare data
byte[] ba = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x22, 0x33, 0x44, 0x55, (byte) 0xAA, (byte) 0xCC, (byte) 0xFF };
ByteBuffer myPict = ByteBuffer.wrap(ba);
String myId = "1234567890";
String myName = "mickey";
int myAge = 50;
logger.info("We try id=" + myId + ", name=" + myName + ", age=" + myAge +", pict=" + hexDump(myPict));
cassandraOps.insert(new Person(myId, myAge, myName, myPict ));
Select s = QueryBuilder.select("id","name","age","pict").from("person");
s.where(QueryBuilder.eq("id", myId));
ResultSet rs = cassandraOps.query(s);
Row r = rs.one();
logger.info("We got id=" + r.getString(0) + ", name=" + r.getString(1) + ", age=" + r.getInt(2) +", pict=" + hexDump(r.getBytes(3)));
} catch (Exception e) {
e.printStackTrace();
}
}
}
--- http://projects.spring.io/spring-data-cassandra/で説明されているように、cassandra 用の単純な Spring プロジェクトを構成したと仮定します。
実際の実行結果は次のとおりです。
[main] INFO org.spring.cassandra.example.CassandraApp - id=1234567890, name=mickey, age=50, pict= 0001020304051122334455AACCFFを試す
[main] INFO org.spring.cassandra.example.CassandraApp - We got id=1234567890, name=mickey, age=50, pict=8200000800000073000000020000000100000004000A6D796B657973706163650006706572736F6E00026964000D00046E616D65000D000361676500090004706963740003000000010000000A31323334353637383930000000066D69636B657900000004000000320000000E 0001020304051122334455AACCFF
cqlshコマンドラインから見られるように、挿入はデータベース自体で正しく見えますが:
cqlsh:mykeyspace> select * from person;
id | age | name | pict
------------+-----+--------+--------------------------------
1234567890 | 50 | mickey | 0x0001020304051122334455aaccff
(1 rows)