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のサンプルを見たり、色々苦労しました...