Java data mapper for Amazon SimpleDB
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.settings
src
.classpath
.gitignore
.project
LICENCE.txt
README.md
pom.xml

README.md

simpledb-mapper

simpledb-mapperは、Amazon SimpleDBのデータマッパーユーティリティです。ドメインをPOJOとして表現し、アノテーションをつけるだけでSimpleDBに永続化が可能です。(いくつか制限があります) イメージとしてはこのような感じです。

AWSCredentials cred = new BasicAWSCredentials(accessKey, secretKey);;
AmazonSimpleDB sdb = new AmazonSimpleDBClient(cred);
sdb.setEndpoint("sdb.ap-northeast-1.amazonaws.com");
AmazonS3 s3 = new AmazonS3Client(cred);

SimpleDBMapper mapper = new SimpleDBMapper(sdb, s3);

Book book1 = new Book();
book1.id = 123L;
book1.title = "面白い本";
book1.authors = new HashSet<String>();
book1.authors.add("著者A");
book1.authors.add("著者B");
book1.price = 1280;
book1.publishedAt = new Date();
book1.isbn = "1234567890";
book1.width = 18.2f;
book1.height = 25.6f;
book1.available = true;

mapper.save(book1);

Usage

始めに、SimpleDBにドメインを作成します。ドメインを作成するメソッドがSimpleDBMapperにあります。

SimpleDBMapper mapper = new SimpleDBMapper(sdb, s3);
mapper.createDomain(Book.class);

SimpleDBに永続化したいモデルをPOJOとして表現し、そこにsimpledb-mapperが用意してあるアノテーションを付け加えます。以下、サンプルとしてBookというPOJOを例に解説します。

@SimpleDBDomain(
		domainName = "SimpleDBMapper-Book-Testing", 
		s3BucketName = "simpledbmapper-book-testing", 
		s3KeyPrefix = "simpledb-blob/")
public class Book {
 	@SimpleDBItemName
	public Long id;
 	
	@SimpleDBAttribute
	public String title;

	@SimpleDBAttribute(attributeName = "isbn")
	public String isbn;

	@SimpleDBAttribute
	public Set<String> authors; 

	@SimpleDBAttribute
	public Date publishedAt;
	
	@SimpleDBAttribute
	public Integer price;
 
	@SimpleDBAttribute
	public Float height;
 
	@SimpleDBAttribute
	public Float width;
 	
	@SimpleDBAttribute
	public boolean available;

	@SimpleDBBlob(contentType = "text/plain")
	public String review;

	@SimpleDBBlob(contentType = "image/jpeg", fetch = FetchType.LAZY)
	public byte[] coverImage;

	@SimpleDBVersionAttribute
	public Long version;
}

@SimpleDBDomain

永続化したいPOJOの指定です。

domainName
ドメイン名(必須)
s3BucketName
BlobをS3に保存する際のバケット名
s3KeyPrefix
BlobをS3に保存する際のキーの名前のはじまり部分

この例で言うと、「SimpleDBMapper-Book-Testing」に永続化されます。(リレーショナルデータベースで言い換えれば、テーブルの指定に相当します。)Blobが指定されているreviewとcoverImageは「simpledbmapper-book-testing」というS3バケット内の「sampled-blob/」以下に保存されます。

###@SimpleDBItemName @SimpleDBItemNameアノテーションを指定されたフィールドは、SimpleDBのItemNameにひもづけられます。(リレーショナルデータベースで言い換えれば、プライマリキーに相当します。)ItemNameとして指定できる型は以下に制約されます。

  • java.lang.String
  • java.lang.Integer
  • java.lang.Float
  • java.lang.Long

###@SimpleDBAttribute @SimpleDBAttributeアノテーションを指定されたフィールドは、SimpleDBのattributeにひもづけられます。(リレーショナルデータベースで言い換えれば、カラムに相当します。) attributeとして指定できる型は以下に制約されます。

  • java.lang.String
  • java.lang.Integer
  • java.lang.Float
  • java.lang.Long
  • java.util.Date
  • java.util.Set<java.lang.String>
  • java.util.Set<java.lang.Integer>
  • java.util.Set<java.lang.Float>
  • java.util.Set<java.lang.Long>
  • java.util.Set<java.util.Date>

アノテーションでは以下を指定する事が可能です。

attributeName
SimpleDBの属性名指定。省略時はフィールド名が使用されます。
フォーマンスは大幅に落ちます。指定には、FetchType.EAGERかFetchType.LAZYを指定します。simpledb-mapperは、遅延ロードのような機能はサポートしていません。単に取得しないだけです。

###@SimpleDBBlob @SimpleDBBlobアノテーションで指定されたフィールドは、SimpleDBの制限である1024byteを超える大きなデータを永続化したい場合に使います。データそのものはS3に保存され、SimpleDBのアトリビュートにはその参照情報(バケット名、キーなど)が記載されます。simpledb-mapperはその参照情報をもとに自動的にPOJOにデータをセットします。

指定できる型は

  • java.lang.String
  • byte[]

のみです。

アノテーションでは以下を指定する事が可能です。

attributeName
SimpleDBの属性名指定。省略時はフィールド名が使用されます。
contentType
S3に保存する際のContent-Type指定
fetch
S3より随時データを取得するかどうか。デフォルトでは常に取得しますが、パフォーマンスは大幅に落ちます。指定には、FetchType.EAGERかFetchType.LAZYを指定します。simpledb-mapperは、遅延ロードのような機能はサポートしていません。単に取得しないだけです。

なお、FetchType.LAZYで指定されたフィールドを上書きしてフェッチ対象にするためにはこのようにします。

mapper.addEagerBlobFetch("coverImage");

フェッチ対象から再度外すにはこのようにします。

mapper.removeEagerBlobFetch("coverImage");
//もしくは
mapper.resetEagerBlobFetch();

###@SimpleDBVersionAttribute @SimpleDBVersionAttributeアノテーションで指定されたフィールドは、SimpleDBにアイテムをPUT/DELETEする際にトランザクション制御(楽観的ロック)を実現するためのフィールドになります。このフィールドはsimpledb-mapperが内部的に使用するものです。この指定は必須ではありません。 指定できる型は

  • java.lang.Long

のみです。

Install

Mavenのリポジトリを用意してありますので、pom.xmlに以下の記述を追加してください。

<repositories>
	<repository>
		<id>dateofrock</id>
		<url>https://s3-ap-northeast-1.amazonaws.com/dateofrock-repository/maven/</url>
	</repository>
</repositories>
<dependencies>
	<dependency>
		<groupId>com.dateofrock.aws</groupId>
		<artifactId>simpledb-mapper</artifactId>
		<version>0.7-SNAPSHOT</version>
	</dependency>
</dependencies>

なお、simpledb-mapperはAWS SDK for Javaライブラリを利用しています。

Usage

はじめにAWSのSDKで用意されているAmazonSimpleDBAmazonS3のインスタンスを作ります。SimpleDBで使いたいリージョンがUS-EAST以外の場合は、相応のEndPoint指定が必要です。それらをsimpledb-mapperのSimpleDBMapperのコンストラクタに渡してください。

AWSCredentials cred = new BasicAWSCredentials(accessKey, secretKey);;
AmazonSimpleDB sdb = new AmazonSimpleDBClient(cred);
sdb.setEndpoint("sdb.ap-northeast-1.amazonaws.com"); 
AmazonS3 s3 = new AmazonS3Client(cred);

SimpleDBMapper mapper = new SimpleDBMapper(sdb, s3);

@SimpleDBEntityアノテーションが指定されたPOJOを用意します。simpledb-mapperではItemNameの自動生成をサポートしていませんので、自分で作る必要があります。

Book book = new Book();
book.id = 123L;
book.title = "スベらないプレゼン";
book.authors = new HashSet<String>();
book.authors.add("恥 忍");
book.authors.add("恥 晒");
book.price = 480;
book.publishedAt = toDate("2015-3-10 00:00:00");
book.isbn = "0987654321";
book.width = 18.2f;
book.height = 23.0f;
book.available = false;
book.review = readUTF8String("/book2.review.txt"); //大きなテキストなど
book.coverImage = readBytes("/book2.cover.jpg"); //JPEG画像など

SimpleDBMapper#save()でSimpleDBに永続化されます。

mapper.save(book);

book1のattributeを変更して、再度save()すると、上書き保存されます。(リレーショナルデータベースで言うところのUPDATEになります。)

book.authors.remove("恥 晒");
mapper.save(book);

SimpleDBに永続化されたPOJOを取得したい場合はやり方が二種類あります。一つはItemNameを指定する方法、もう一つはQueryを投げる方法です。

// ItemNameを指定する方法
Book fetchedBook = mapper.load(Book.class, 123L);

// Queryを指定する方法 
Condition condition = new Condition("title", Like, "スベらない%");
QueryExpression expression = new QueryExpression(condition);
expression.addAndCondition(new Condition("publishedAt", GreaterThan, toDate("2010-01-01 00:00:00"));
Sort sort = new Sort(DESC, "publishedAt");
expression.setSort(sort);
expression.setLimit(100);
 
List<Book> books = mapper.query(Book.class, expression);

Queryはこのように書く事も可能です。

List<Book> books = mapper.from(Book.class)
	.where("title", Like, "スベらない%"))
	.and("publishedAt", GreaterThan, toDate("2010-01-01 00:00:00"))
	.orderBy("publishedAt", DESC)
	.limit(100)
	.fetch();

booksが大量にある場合、QueryExpressionにLimitをセットしてください。セットしない場合はSimpleDBのデフォルト値である100がセットされます。また、セットできる最大値はSimpleDBの制限から2500です。

expression.setLimit(1000);

queryを投げた際に、さらに残りのアイテムがある場合は、SimpleDBMapper#hasNext()を呼んでください。つまりコードは以下のようになるでしょう。

List<Book> books = mapper.query(Book.class, expression);
while (mapper.hasNext()) {
	books.addAll(Book.class, expression);
}

削除する場合は、ItemNameに値が入っているPOJOを引数にdelete()を呼びます。

mapper.delete(book);

アイテムのカウントをする事も可能です。条件なしにすべてのアイテムをカウントする方法と条件付きカウントの二種類があります。

// 条件なし
int count = mapper.countAll(Book.class, true);
// 条件あり
count = mapper.count(Book.class, expression);

Tips

S3へのアップロード速度を上げる

Blobフィールドが多くあると、S3へのアクセスに時間がかかるケースがあります。その場合はS3に並列で読み書きするのがベストな方法です。

simpledb-mapperでは、S3に書き込む際のスピードを上げるために、並列度の設定をする事が出来ます。(とはいえ、読み込みは未実装です。ごめんなさい。)その設定は、SimpleDBMapperのインスタンスを作る際に、SimpleDBMapperConfigを渡してあげる事です。

SimpleDBMapperConfig config = new SimpleDBMapperConfig();
config.setS3AccessThreadPoolSize(3); //同時にS3にアクセスするスレッド数が3になる。
SimpleDBMapper mapper = new SimpleDBMapper(sub, s3, config);

スレッド数はデフォルトでは「2」です。この数の最適値は一概には言えませんが、POJOに設定してあるBlobの数と一致させるのが一般的です。ただし、その分メモリの消費量も増えますのでご注意ください。

Consistent Readオプション

SimpleDBにはデータ読み出しの一貫性を保証するConsistent Readオプションがあります。simpledb-mapperのデフォルトではtrueになっていますが、ここをfalseにする事によって読み出しパフォーマンスを上げる事が可能です。これも、SimpleDBMapperConfigにセットします。

config.setConsistentRead(false);

Consistent Readをfalseにすると、SimpleDBより読み出したデータが古い可能性があります。作りによってはアプリケーション内で矛盾が発生する可能性があるので、十分に注意してください。なお、SimpleDBは1秒程度で一貫性が保たれるという事です。(参考「SimpleDB, SQS, SNS詳細 - AWSマイスターシリーズ」)

Limitation

Licence

  • ソースコードはApache Licence 2.0とし、すべてをgithub上に公開する事とします。(https://github.com/dateofrock/simpledb-mapper
  • 当ソフトウェアの動作は保証しません。ご自身の責任と判断でご利用ください。
  • 当ソフトウェアを利用することにより発生したいかなる損害も当方は責任を負わないものとします。

Author

Takehito Tanabe - dateofrock