Cassandra に Java でアクセス

Cassandra に Java でアクセスする方法について、試行錯誤した内容をまとめます。
アクセスには高レベルAPIと低レベルAPIの2種類方法があるのですが、ここでは低レベルAPIについて記載しています。

Cassandra の最新版(2011年6月3日時点で0.7.6-2)の場合、公式ページにあるサンプルでは、コンパイルが通りません。おそらく API が変わったのだと思われます。

サンプルと同じ内容のプログラムを、0.7.6-2でコンパイルおよび実行可能なように書き直したものが以下です。

import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.List;

import org.apache.cassandra.thrift.Cassandra;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.thrift.ColumnOrSuperColumn;
import org.apache.cassandra.thrift.ColumnParent;
import org.apache.cassandra.thrift.ColumnPath;
import org.apache.cassandra.thrift.ConsistencyLevel;
import org.apache.cassandra.thrift.InvalidRequestException;
import org.apache.cassandra.thrift.NotFoundException;
import org.apache.cassandra.thrift.SlicePredicate;
import org.apache.cassandra.thrift.SliceRange;
import org.apache.cassandra.thrift.TBinaryProtocol;
import org.apache.cassandra.thrift.TimedOutException;
import org.apache.cassandra.thrift.UnavailableException;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

/**
 * @author hatanaka
 */
public class CassandraTest {
    /** キースペース */
    public static final String KEYSPACE = "Keyspace1";

    /** カラムファミリー */
    public static final String COLUMN_FAMILY = "Standard2";

    /**
     * @param args
     */
    public static void main(String[] args) {
        TSocket socket = new TSocket("192.168.28.129", 9160);
        TTransport transport = new TFramedTransport(socket);
        //TSocketを直接引数に取れるが、TFramedTransportでないと、以降の処理でエラー
        TProtocol protocol = new TBinaryProtocol(transport);
        Cassandra.Client client = new Cassandra.Client(protocol);
        try {
            transport.open();
            client.set_keyspace(KEYSPACE);
            final long timestamp = System.currentTimeMillis();
            //特定キーに1件カラムをインサート
            client.insert(strToBB("test"),
                          new ColumnParent(COLUMN_FAMILY),
                          new Column(strToBB("sample1"),
                                     strToBB("サンプルの値"),
                                     timestamp),
                          ConsistencyLevel.ONE);
            System.out.println("インサート完了.");

            //特定キーの特定カラムの値を取得
            ColumnPath path = new ColumnPath(COLUMN_FAMILY);
            path.setColumn(strToBB("sample1"));
            ColumnOrSuperColumn column = client.get(strToBB("test"),
                                                    path,
                                                    ConsistencyLevel.ONE);
            System.out.println(byteToStr(column.getColumn().getName()) + ":"
                    + byteToStr(column.getColumn().getValue()));

            //特定キーの全カラムの値を取得
            SlicePredicate predicate = new SlicePredicate();
            predicate.setSlice_range(new SliceRange(ByteBuffer.wrap(new byte[0]),
                                                    ByteBuffer.wrap(new byte[0]),
                                                    false,
                                                    10));
            List<ColumnOrSuperColumn> columns = client.get_slice(strToBB("test"),
                                                                 new ColumnParent(COLUMN_FAMILY),
                                                                 predicate,
                                                                 ConsistencyLevel.ONE);
            for (ColumnOrSuperColumn aColumn : columns) {
                System.out.println(byteToStr(aColumn.getColumn().getName())
                        + ":" + byteToStr(aColumn.getColumn().getValue()));
            }
        } catch (InvalidRequestException e) {
            throw new RuntimeException(e);
        } catch (UnavailableException e) {
            throw new RuntimeException(e);
        } catch (TimedOutException e) {
            throw new RuntimeException(e);
        } catch (TException e) {
            throw new RuntimeException(e);
        } catch (NotFoundException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                transport.flush();
            } catch (TTransportException e) {
                throw new RuntimeException(e);
            } finally {
                transport.close();
            }
        }
    }

    /**
     * String から ByteBuffer へのコンバータ
     * @param msg String
     * @return ByteBuffer
     */
    private static ByteBuffer strToBB(String msg) {
        Charset charset = Charset.forName("UTF-8");
        return ByteBuffer.wrap(msg.getBytes(charset));
    }

    /**
     * byte[] から String へのコンバータ
     * @param buf byte[]
     * @return String
     */
    private static String byteToStr(byte[] buf) {
        Charset charset = Charset.forName("UTF-8");
        return new String(buf, charset);
    }
}

挿入検索のメソッドの引数が違っているのと、キーストアの指定の仕方も違っています。
簡単なプログラムなのに、perlのサンプルを見たり、色々苦労しました...