次世代DaoフレームワークDoma

6,408 views
6,225 views

Published on

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,408
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
22
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

次世代DaoフレームワークDoma

  1. 1. 次世代 Dao フレームワーク Doma (ドマ) 第 56 回 JavaEE 勉強会 中村年宏 ( http://d.hatena.ne.jp/taedium/)
  2. 2. Doma (ドマ)とは <ul><li>D omain O riented MA pping Framework </li></ul><ul><ul><li>Domain (ドメイン) = 値の定義域 </li></ul></ul><ul><ul><li>Doma では String や Integer の定義域をより狭めたものを Domain (ドメイン)と呼ぶ </li></ul></ul><ul><li>名前だけだと汎用的だけど、カテゴリとしては Dao フレームワーク( O/R マッパー) </li></ul><ul><li>Java6 ( JDBC4.0 )対応 </li></ul><ul><li>他のライブラリに依存していない </li></ul><ul><li>Seasar プロジェクトの Sandbox で開発中 </li></ul><ul><ul><li>SVN リポジトリ </li></ul></ul><ul><ul><ul><li>https://www.seasar.org/svn/sandbox/doma/ </li></ul></ul></ul><ul><ul><li>SNAPSHOT </li></ul></ul><ul><ul><ul><li>http://maven.seasar.org/maven2-snapshot/org/seasar/doma/doma/0.9.0-SNAPSHOT/ </li></ul></ul></ul><ul><ul><li>ドキュメント </li></ul></ul><ul><ul><ul><li>なし。。。 </li></ul></ul></ul>
  3. 3. Doma のコンセプト <ul><li>Domain(ドメイン)中心 </li></ul><ul><li>宣言的プログラミング </li></ul><ul><li>コンパイル時のコード自動生成 </li></ul>
  4. 4. Domain (ドメイン)中心 - ドメインとは? @Entity public class Employee { @Id private Integer id; private String name; private String phoneNumber; // … } @Entity public interface Employee { @Id Identity id(); Name name(); PhoneNumber phoneNumber(); // … } よくある一般的なEntity(JPAとか) Doma の Entity カラムの概念ごとにアプリ固有のクラスを作成(あらかじめ用意されたクラスもあり)。 Domain というインタフェースを実装 。
  5. 5. Domain (ドメイン)中心 – Domain インタフェースとその実装 public interface Domain<V, D extends Domain<V, D>> { V get(); void set(V value); void set(D other); boolean isNull(); boolean isNotNull(); boolean isChanged(); void setChanged( boolean changed); Class<V> getValueClass(); <R, P, TH extends Throwable> R accept(DomainVisitor<R, P, TH> visitor, P p) throws TH; } public class PhoneNumber extends AbstractStringDomain<PhoneNumber> { private static final long serialVersionUID = 1L; public PhoneNumber() { } public PhoneNumber(String value) { super (value); } } Domainインタフェース 実装例 String とか Integer のラッパーみたいなもの。 ここでは DB の型とのマッピング情報もたない。 Visitor パターンで RDBMS ごとにマッピング。 抽象クラスが用意されているので通常は継承するだけ。 直接 Domain インタフェースを実装することも可。 好きなメソッドを定義できる。
  6. 6. Domain (ドメイン)中心 – なぜ? <ul><li>意図を明確に表せる </li></ul><ul><li>値に特化したメソッドを持てる </li></ul><ul><ul><li>PhoneNumber に国番号を扱うメソッドをもつとか </li></ul></ul><ul><ul><li>ひとつのカラムに複数の意味をもたせたレガシーな設計に対応しやすい </li></ul></ul><ul><li>より安全 </li></ul><ul><ul><li>違う型で代入しようとすればコンパイルエラー </li></ul></ul>要するに、概念が異なるものは違うクラスでリッチに扱おうよということ。
  7. 7. 宣言的プログラミング – Entity の場合 @Entity public class Employee { @Id private Integer id; private String name; private String phoneNumber; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } // … } @Entity public interface Employee { @Id Identity id(); Name name() ; PhoneNumber phoneNumber() ; // … } よくある一般的なEntity Doma の Entity Doma の Entity はインタフェースで定義する。 メソッドは null を返さない。
  8. 8. 宣言的プログラミング – Dao の場合 @Dao(config = AppConfig.class) public interface EmployeeDao { @Select(fetchSize = 50) Employee selectById(Identity id); @Insert(excludeNull = true) int insert(Employee employee); } Doma の Dao Doma では、アノテーションでクエリの種別を指定する。フェッチサイズ等の指定もアノテーションで記述できる。 意図が明確。間違いにくい。 @S2Dao(bean = Employee.class) public interface EmployeeDao { Employee selectById (Integer id); int insert (Employee employee); } S2DaoのDao S2Daoでは命名規約でクエリの種別を指定。フェッチサイズなどいくつかの設定は設定ファイルで指定。 + 設定ファイル
  9. 9. コンパイル時のコード生成 <ul><li>Pluggable Annotation Processing API を利用 </li></ul><ul><ul><li>Java6 から導入された機能 </li></ul></ul><ul><ul><ul><li>apt と呼ばれることも </li></ul></ul></ul><ul><ul><li>Javac はもちろん Eclipse も対応している </li></ul></ul><ul><ul><ul><li>Save したときにコード生成 </li></ul></ul></ul><ul><ul><ul><li>コードの依存関係をみて賢く生成 </li></ul></ul></ul><ul><ul><ul><li>エラーメッセージをエディタ上に表示 </li></ul></ul></ul>
  10. 10. コンパイル時のコード生成 – 例 @Override public org.seasar.doma.it.entity.Employee selectById(org.seasar.doma.it.domain.Identity employee_id) { entering(&quot;org.seasar.doma.it.dao.EmployeeDao_&quot;, &quot;selectById&quot;, employee_id); if (employee_id == null ) { throw new org.seasar.doma.DomaIllegalArgumentException(&quot;employee_id&quot;, employee_id); } org.seasar.doma.internal.jdbc.query.SqlFileSelectQuery query = new org.seasar.doma.internal.jdbc.query.SqlFileSelectQuery(); query.setConfig(config); query.setSqlFilePath(org.seasar.doma.internal.jdbc.sql.SqlFiles.buildPath(&quot;org.seasar.doma.it.dao.EmployeeDao&quot;, &quot;selectById&quot;)); query.addParameter(&quot;employee_id&quot;, employee_id); query.setCallerClassName(&quot;org.seasar.doma.it.dao.EmployeeDao_&quot;); query.setCallerMethodName(&quot;selectById&quot;); query.setQueryTimeout(-1); query.setMaxRows(-1); query.setFetchSize(-1); query.compile(); org.seasar.doma.internal.jdbc.command.SelectCommand<org.seasar.doma.it.entity.Employee> command = new org.seasar.doma.internal.jdbc.command.SelectCommand<org.seasar.doma.it.entity.Employee>(query, new org.seasar.doma.internal.jdbc.command.EntitySingleResultHandler<org.seasar.doma.it.entity.Employee, org.seasar.doma.it.entity.Employee_>(org.seasar.doma.it.entity.Employee_. class )); org.seasar.doma.it.entity.Employee result = command.execute(); exiting(&quot;org.seasar.doma.it.dao.EmployeeDao_&quot;, &quot;selectById&quot;, result); return result; } @Select Employee selectById(Identity employee_id); インターフェースのメソッド 生成される実装クラスのコード 実行時にリフレクションやAOPで同等のことをするよりも ・パフォーマンスがいい。 ・挙動を把握しやすい。 デバッグがしやすい(デバッグポイントを置きやすい)のもポイント。 利点
  11. 11. Doma の機能 – 概要 <ul><li>複数 RDBMS 対応 </li></ul><ul><ul><li>今は HSQLDB 、 Oracle 、 PostgerSQL 、 MySQL </li></ul></ul><ul><li>2WaySQL </li></ul><ul><ul><li>自動生成 & SQL ファイル </li></ul></ul><ul><li>Entity リスナー </li></ul><ul><ul><li>更新前に汎用的な処理を実行できる </li></ul></ul><ul><ul><ul><li>タイムスタンプや更新者の設定とか </li></ul></ul></ul><ul><li>コンパイル時のエラーチェック </li></ul><ul><ul><li>規約に外れたものをチェック </li></ul></ul><ul><ul><li>SQL ファイルの存在チェック </li></ul></ul><ul><ul><li>コメント式のチェック </li></ul></ul>
  12. 12. Doma の機能 – SQL 関連 <ul><li>検索系 </li></ul><ul><ul><li>Dao のメソッドに @Select をつける </li></ul></ul><ul><ul><li>自動生成しない。 SQL ファイルとのマッピングのみサポート。 </li></ul></ul><ul><ul><li>SQL への変換機能あり(ページング、悲観的ロック)。 </li></ul></ul><ul><ul><li>1 件ずつの処理可能。 </li></ul></ul><ul><li>更新系 </li></ul><ul><ul><li>Dao のメソッドに @Insert 、 @Update などをつける </li></ul></ul><ul><ul><li>自動生成する。 SQL ファイルへのマッピングも可能。 </li></ul></ul><ul><ul><li>Update は変更のあったプロパティのみを対象。 </li></ul></ul><ul><ul><li>バッチ更新にも対応。 </li></ul></ul><ul><li>プロシージャ & ファンクション </li></ul><ul><ul><li>Dao のメソッドに @Procedure や @Function をつける </li></ul></ul>@Procedure(name=&quot;hoge&quot;) void execute (@In Name name, @InOut Salary salary, @Out PhoneNumber phoneNumber); 例
  13. 13. Doma の機能 – SQL ファイル関連 <ul><li>ファイルは Dao ごとに管理 </li></ul><ul><li>SQL コメントのルールは S2Dao に似た感じ </li></ul>select * from employee where name = /*name*/ ’hoge’ select * from employee where /*%if name. startsWith (“A”)*/ name = /*name*/ ’hoge’ --else name isnull /*%end*/ select * from employee where /* %if name != null*/ name = /*name*/ ’hoge’ /* %end */ If 文を使える Method 呼び出し可 else も使える バインド変数はコメントで表す。 メソッドのパラメータ名にあわせる。 @Select selectByName(Name name); Daoのメソッド SQLの例
  14. 14. Doma の機能 – apt 関連 <ul><li>SQLファイルの存在チェック </li></ul><ul><ul><li>SQLファイルが必要なDaoメソッドに対応するファイルが存在しない場合はエラーメッセージを表示。 </li></ul></ul><ul><li>SQLコメントのチェック </li></ul>select * from employee where name = /*emp_name*/ ’hoge’ @Select selectByName(Name name ); メソッドのパラメータに存在しない名前がSQLコメントで使用されたらエラー。
  15. 15. デモ Doma は、 Java6 で動作します。 Java5 以前はサポートしてません。 IDE は Eclipse3.5 で動作することを確認しています。( 3.4 だと動かないところあるかも。) apt をサポートしていれば Eclipse でなくても大丈夫だと思います。 Eclipseで動作させるためのポイント <ul><li>Doma の jar をビルドパスに通す。 </li></ul><ul><li>Doma の jar を ファクトリパス に通す。設定場所は </li></ul><ul><ul><li>プロジェクト右クリック </li></ul></ul><ul><ul><li>- Properties </li></ul></ul><ul><ul><li>- Java Compiler </li></ul></ul><ul><ul><li>- Annotation Processing ( チェックを入れる ) - Factory Path (チェックを入れる、 jar を登録する) </li></ul></ul>動作させるため注意点
  16. 16. まとめ – Doma の良いところ <ul><li>Domain の利用で意図が明確かつ型安全。 </li></ul><ul><li>明示的な設定。 </li></ul><ul><ul><li>命名規約はない。ルールから外れたら apt で通知。 </li></ul></ul><ul><li>Entity や Dao がすっきり。 </li></ul><ul><ul><li>apt でコード生成。 </li></ul></ul><ul><li>SQL を活かす。 </li></ul><ul><ul><li>2WaySQL 。 </li></ul></ul><ul><ul><li>検索系は 意図的に 自動生成なし。ページングや悲観的ロック用の SQL への変換機能はあり。 </li></ul></ul><ul><li>特定のライブラリに依存しない。 </li></ul><ul><li>S2Dao で問題になっていたことがらの多くを解決している。 </li></ul>

×