BeanKeeper
BeanKeeper はシンプルなORマッパーです。設定ファイルを書く必要がなく、利用方法も明快です。本家は http://beankeeper.netmind.hu/index.php で現在のメジャーリリースバージョンは 2.6 となっています。
特徴として以下が挙げられています。
- 利用方法が簡素で、特別なツールも必要なく数分で使い始められる
- 設定ゼロ
- 小さなフットプリント
- PostgreSQL、MySQL、HSQLDB、Oracle をサポート
- 多様性の完全なサポート
- シンプルで読みやすいクエリ言語
- List、Map、Set などの Collections によるリレーションを扱うことができる
- オブジェクト間の参照や自己参照、循環参照を扱うことができる
- 遅延読み込みのサポート
- Historical 検索が可能
- 複数オブジェクトからの "View" 選択
- 結果リストのキャッシュ
- 分散型のスケーラブルオペレーション
- 構造的、多様的ロックのサポート
セットアップ
今回は 2010/03/17 リリースの beankeeper-2.6.3.tar.gz を使用しました。ソースとpom.xml の配布なので、Maven で以下のように jar 作っておきましょう。
mvn package
なお、今回は HSQLDB 1.8.1 を使用します。現時点では HSQLDB 2系は利用できませんでした。
必要なライブラリは以下となります。
- log4j
- commons-configuration
- commons-lang
- commons-collctions
- commons-logging
- hsqldb-1.8.1.3
- beankeeper-2.6.3
log4j.properties を以下の様に作成しておきます。
log4j.rootLogger=INFO,stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p %d{HH:mm:ss,SSS} %m%n
エンティテイの準備
利用するエンティテイを作成します。
package etc9.domain; import java.util.Date; public class Book { private String title; private Author author; private Date releaseDate; public Book() { } public Book(String title, Author author, Date releaseDate) { this.title = title; this.author = author; this.releaseDate = releaseDate; } ・・・以下getter/setter }
package etc9.domain; public class Author { private String firstName; private String lastName; public Author() { } public Author(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } ・・・以下getter/setter
BeanKeeperの利用
単純な例では、Store を作成して、save と find を使うだけです。
まずは Store の作成。
Store store = new Store("org.hsqldb.jdbcDriver","jdbc:hsqldb:mem:mymemdb");
上記はインメモリDBの例です。ファイルに永続化するには、
Store store = new Store("org.hsqldb.jdbcDriver","jdbc:hsqldb:testdb");
Bean を準備して save するだけでです。
Author author = new Author("Brian", "Kernighan"); Book book = new Book("The C Programming Language", author, DateFormat.getDateInstance().parse("1978/1/1")); store.save(book); List<Book> books = store.find("find book"); for(Book b : books) { System.out.println(b.getTitle()+ " : " + b.getAuthor().getFirstName()); }
以下のような出力が得られます。
The C Programming Language : Brian
削除は以下の通り。
store.remove(book);
クエリ言語
ソートを指定するには以下のように order by が使えます。
find book order by title asc find book order by book.author.firstName
条件指定は以下のように可能です。SQLと同じですね。
find book where title='Java for dummies' "find book where book.author.firstname='Neal' find book where book.title like 'Snow%' and (book.author.firstname='Neal' or book.author.lastname<>'Smith')
1対Nのリレーション
ここではListを使用した例を試します。Book は複数の著者と関連するようにします。
public class Book { private String title; private List<Author> authors; private Date releaseDate; public Book() { } public Book(String title, List<Author> authors, Date releaseDate) { this.title = title; this.authors = authors; this.releaseDate = releaseDate; }
同様に永続化して
Store store = new Store("org.hsqldb.jdbcDriver","jdbc:hsqldb:mem:mymemdb"); Author author1 = new Author("Brian", "Kernighan"); Author author2 = new Author("Dennis", "Ritchie"); Book book = new Book("The C Programming Language", Arrays.asList(author1, author2), DateFormat.getDateInstance().parse("1978/1/1")); store.save(book); List<Book> books = store.find("find book"); for(Book b : books) { System.out.println(b.getTitle()); for(Author a : b.getAuthors()) { System.out.println(" -" + a.getFirstName()); } }
以下のように著者が2人得られます。ようやくK&Rになれました。
The C Programming Language -Brian -Dennis
著者名からbookを得たり、
List<Book> books = store.find("find book where book.authors contains author and author.firstname='Brian'");
著者だけを得ることもできます。
List<Author> authors = store.find("find author where firstname like 'B%'");
エンティテイの更新
取得したBeanを変更して store.save() するだけです。
List<Author> authors = store.find("find author where firstname like 'B%'"); for(Author a : authors) { a.setLastName("*"+a.getLastName()); store.save(a); }
エンティテイのBean自体にプロパティを追加したりした場合も、自動的に処理してくれます。この時永続化したデータはそのままの状態で利用できます。
その他
その他 http://beankeeper.netmind.hu/tutorial.php のチュートリアルを参照してください。
find メソッドとクエリ言語がタイプセーフとならないのが惜しい感じ。