<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
	<properties>
		<title>概要</title>
	</properties>
	<body>
		<section name="目次">
			<ul>
				<li><a href="#概要">概要</a></li>
				<li><a href="#S2Daoから受け継いだアイデアや機能">S2Daoから受け継いだアイデアや機能</a></li>
				<li><a href="#S2Daoからの改善点">S2Daoからの改善点</a></li>
				<li><a href="#Domaの新しい機能">Domaの新しい機能</a></li>
			</ul>
		</section>
		<section name="概要">
			<p>
				Domaは、<a href="http://s2dao.seasar.org/ja/index.html">S2Dao</a>のスタイル（DAOパターンや2 Way SQL）を踏襲したJava6（JDBC4.0）対応のO/Rマッパーです。
				S2Daoの良いアイデアや機能は受け継ぎつつも、扱いにくかったりプログラミングミスにつながりやすかったりする点については積極的に改善を試みています。
				また、aptを利用することで、S2Daoでは実現できなかった新しい機能も提供しています。
			</p>
			<p>
				Domaは、S2Daoの次のアイデアや機能を受け継いでいます。
			</p>
			<ul>
				<li><a href="#DAOパターン">DAOパターン</a></li>
				<li><a href="#a2_Way_SQL">2 Way SQL</a></li>
				<li><a href="#複数RDBMS対応">複数RDBMS対応</a></li>
			</ul>
			<p>
				一方、Domaは、S2Daoの次の点を改善しています。
			</p>
			<ul>
				<li><a href="#Seasar2への依存">Seasar2への依存</a></li>
				<li><a href="#AOPの利用">AOPの利用</a></li>
				<li><a href="#命名規約">命名規約</a></li>
				<li><a href="#JavaとSQLの分離">JavaとSQLの分離</a></li>
				<li><a href="#SQLコメントの文法">SQLコメントの文法</a></li>
				<li><a href="#JDBCを直接利用する方法">JDBCを直接利用する方法</a></li>
				<li><a href="#DaoメソッドとSQLファイルのマッピング">DaoメソッドとSQLファイルのマッピング</a></li>
				<li><a href="#DaoメソッドのパラメータとSQLファイル上のバインド変数コメントのマッピング">DaoメソッドのパラメータとSQLファイル上のバインド変数コメントのマッピング</a></li>
				<li><a href="#Daoの初期化コスト">Daoの初期化コスト</a></li>
			</ul>
			<p>
				さらに、Domaは、新しく次のような機能を提供します。
			</p>
			<ul>
				<li><a href="#コンパイル時のコード生成">コンパイル時のコード生成</a></li>
				<li><a href="#コンパイル時の規約チェック">コンパイル時の規約チェック</a></li>
				<li><a href="#コンパイル時のSQLファイル存在チェックとSQLコメントの文法チェック">コンパイル時のSQLファイル存在チェックとSQLコメントの文法チェック</a></li>
				<li><a href="#アプリケーション固有の値型への対応">アプリケーション固有の値型への対応</a></li>
			</ul>
			<p>
				開発にあたっては、S2Daoのほかに、
				<a href="http://s2container.seasar.org/2.4/ja/s2jdbc.html">S2JDBC</a>や<a href="http://www.hibernate.org/">Hibernate</a>や<a href="http://dbflute.sandbox.seasar.org/">DBFlute</a>を参考にしています。
			</p>
		</section>
		<section name="S2Daoから受け継いだアイデアや機能">
			<subsection name="DAOパターン">
				<p>
					DomaではS2Daoと同様にDAOパターンを採用しています。
				</p>
				<p>
					DAOパターンを採用するのは、次のような利点があるからです。
				</p>
				<ul>
					<li>データアクセスの箇所を特定しやすい</li>
					<li>データアクセス処理をカプセル化できる（SQLの自動生成処理をJDBCを直接利用した処理に変更しても利用側プログラムに影響を与えない）</li>
					<li>テストをしやすい（モックを作成しやすい）</li>
				</ul>
			</subsection>
			<subsection name="2 Way SQL">
				<p>
					S2Daoでは、外部ファイルに記述したSQLを、Javaとマッピングした形でフレームワークの一部として取り込むことも、単独でSQLツール上で実行することも可能としています（2 Way SQL）。
				</p>
				<p>
					Domaでは、このアイデアをそのまま採用しています。ただし、マッピングルールやSQLコメントの用い方については変更を加えています。
				</p>
				<p>
					2 Way SQLは、フレームワークで扱うSQLを単独でテストしたり、Java開発者とSQL作成者の作業を分離したりするのに非常に有効な方法です。
				</p>
			</subsection>
			<subsection name="複数RDBMS対応">
				<p>
					S2Daoでは、SQLファイル名にRDBMS名を含めることで特定のRDBMS専用のSQLを用意できました。
					例えば、「EmployeeDao_selectByName.sql」という名前のSQLファイルと「EmployeeDao_selectByName_oracle.sql」という名前のSQLファイルが存在する場合、
					拡張子の直前にアンダースコア区切りで「oracle」という名前が記述されている後者のファイルがOracle Database専用のSQLファイルになります。
					このファイルはOracle Databaseに接続している場合にのみ使用され、それ以外のRDBMSでは「EmployeeDao_selectByName.sql」が使用されます。
				</p>
				<p>
					Domaでも、このアイデアをほぼそのまま採用しています。
					ただし、SQLファイルにRDBMS名を含めるルールをアンダースコアではなくハイフンに変更しています。
					例えば、Oracle Database専用のSQLファイルは「selectByName-oracle.sql」という名前になります。
				</p>
				<p>
					RDBMSごとにSQLを切り替える手法は、フレームワークで吸収するのが困難なRDBMS独自のSQLを活用したい場合に役立ちます。
				</p>
			</subsection>
		</section>
		<section name="S2Daoからの改善点">
			<subsection name="Seasar2への依存">
				<p>
					S2Daoを利用するには、Seasar2のライブラリが必須でした。
				</p>
				<p>
					一方、Domaでは、Seasar2への依存が一切ありません。このため、<a href="http://www.springsource.org/">Spring Framework</a>や<a href="http://code.google.com/p/google-guice/">Guice</a>といったSeasar2以外のDIコンテナと組み合わせやすくなっています。
					また、単独で利用することも可能です。
					Domaはdoma-x.x.x.jarというたった1つのjarファイルのみで動作します。
				</p>
			</subsection>
			<subsection name="AOPの利用">
				<p>
					S2Daoでは、実行時にDaoのインタフェースにAOPを適用することで動作していました。
				</p>
				<p>
					一方、Domaでは、コンパイル時にaptでインタフェースから実装クラスをソースコードとして生成し、実行時には生成されたソースコードに対応する実装クラスを使用します。
				</p>
				<p>
					AOPは便利な機能ですが、挙動が把握しにくかったりデバッグがしにくかったりといった問題点がありました。
					Domaではこれらの問題点を避けるため、AOPではなくaptによるコード生成を利用しています。
				</p>
				<p>
					ただし、S2DaoであれDomaであれ、アプリケーション開発者が作成するのはインタフェースのみという点は同じです。
				</p>
			</subsection>
			<subsection name="命名規約">
				<p>
					S2Daoでは、たとえば、Daoのメソッド名が「update」で始まる場合そのメソッドはUPDATE文を発行するメソッドである、といった命名規約を持っていました。
				</p>
<source><![CDATA[int updateEmployee(Employee employee);]]></source>
				<p>
					一方、Domaでは、暗黙的な命名規約ではなく、アノテーションを採用しています。
					たとえば、UPDATE文を発行するメソッドには@Updateを注釈します。
					メソッド名に制約はありません。
					Domaでは、アノテーションを利用することで意図をより明確にプログラムコード上に表現し、挙動をわかりやすくしています。
				</p>
<source><![CDATA[@Update
int save(Employee employee);]]></source>
			</subsection>
			<subsection name="JavaとSQLの分離">
				<p>
					S2Daoでは、DaoのメソッドにアノテーションでSQL全体やSQLの一部を記述することを認めていました。
				</p>
				<p>
					Domaでは、DaoのメソッドにアノテーションでSQLの全体や一部を記述することを認めません。
					JavaのコードにSQLを記述することは、アプリケーションの保守性を損ねるからです。
					SQLの記述は、すべて外部ファイルで行うことになっています。
				</p>
			</subsection>
			<subsection name="SQLコメントの文法">
				<p>
					S2Daoでは、SQLに含まれたSQLコメントの前後にスペースがあるかどうかの違いでエラーが発生するなど非常に細かな間違いやすい文法を持っていました。
					また、間違いが含まれていた場合のエラーメッセージもわかりにくいものでした。
				</p>
				<p>
					Domaでは、文法を見直し厳密にしました。また、aptで検証することで、間違いがあっても「コンパイル」時にエラーを検出し、わかりやすいメッセージを表示するようにしています。
					実行しなくてもエラーの有無を確認できるのは、S2Daoに比べて大きな利点です。
				</p>
			</subsection>
			<subsection name="JDBCを直接利用する方法">
				<p>
					S2Daoでは、Daoの特定のメソッドでJDBCを直接利用するには、インタフェースの実装クラスを作成しメソッドをオーバーライドしなければいけませんでした。
					クラス名を設定ファイル等に記述している場合、この方法では、設定を変更する必要がありました。
				</p>
<source><![CDATA[@S2Dao(bean = Employee.class)
public interface EmployeeDao {
    Employee selectByName(String name);
}]]></source>
<source><![CDATA[public abstract class AbstractEmployeeDao implements EmployeeDao {
    @Override
    public List<Employee> selectByName(String name) {
        ...
    }
}]]></source>
				<p>
					Domaでは、@Delegateというアノテーションを使って、JDBCを直接利用する処理を別クラスに委譲できます。
				</p>
<source><![CDATA[@Dao(config = AppConfig.class)
public interface EmployeeDao {
    @Delegate(to = EmployeeDaoDelegate.class)
    List<Employee> selectByName(String name);
}]]></source>
<source><![CDATA[public class EmployeeDaoDelegate {
    ...
    public List<Employee> selectByName(String name) {
        ....
    }
}]]></source>
				<p>
					この方法は、クラス階層に変更を加えないためより柔軟です。
					たとえ、クラス名が設定ファイルに記述されていても変更を加える必要がありません。
				</p>
				<p>
					詳細は、<a href="reference/dao.html#デリゲート定義">デリゲート定義</a>を参照してください。
				</p>
			</subsection>
			<subsection name="DaoメソッドとSQLファイルのマッピング">
				<p>
					S2Daoでは、SQLファイルをDaoと同じパッケージに配置しなければいけませんでした。
					この仕様では、Daoが同じパッケージに複数存在する場合に、ひとつのパッケージ内に存在するSQLファイルが多くなりすぎて管理が難しくなります。
				</p>
				<p>
					Domaでは、Daoごとに異なるディレクトリでSQLファイルを管理する仕様になっています。
					このため、SQLファイルをDaoごとに管理しやすくなっています。
					また、DaoメソッドとSQLファイルを相互に遷移する<a href="extension/doma_tools.html">Eclipseプラグイン</a>を用意しているので、これを使うとさらに開発/管理がしやすくなります。
				</p>
				<p>
					詳細は、<a href="reference/sqlfile.html#SQLファイル">SQLファイル</a>を参照してください。
				</p>
			</subsection>
			<subsection name="DaoメソッドのパラメータとSQLファイル上のバインド変数コメントのマッピング">
				<p>
					S2Daoでは、メソッドのパラメータがSQLファイル内のバインド変数コメントで参照できるようにArgumentsアノテーションを使用してパラメータごとに名前をつける必要がありました。
				</p>
<source><![CDATA[@Arguments( { "job", "salary" })
List<Employee> selectEmployeeByJobDeptno(String job, BigDecimal salary);]]></source>
				<p>
					Domaでは、Argumentsアノテーションに相当するものは不要です。aptによりメソッドのパラメータ名をそのまま使用できるからです。
				</p>
<source><![CDATA[@Select
List<Employee> selectEmployeeByJobDeptno(String job, BigDecimal salary);]]></source>
			</subsection>
			<subsection name="Daoの初期化コスト">
				<p>
					S2Daoでは、Daoの最初のアクセス時に、Daoのメタ情報を作成するための初期化コストがかかっていました。
					ここでのメタ情報とは、どのメソッドがどのCRUDに相当するのか、そのメソッドではSQLを自動生成するのかSQLファイルにマッピングするのかといった情報です。
				</p>
				<p>
					Domaでは、コンパイル時にメタ情報をソースコードで表現し、実行時にはそのソースコードに対応するバイトコードを実行するため、そのようなコストがありません。
				</p>
			</subsection>
		</section>
		<section name="Domaの新しい機能">
			<subsection name="コンパイル時のコード生成">
				<p>
					aptを使い、コンパイル時にコードを生成できます。
					たとえば、次のインタフェースをコンパイルすると、インタフェースの実装クラスが自動生成されます。
				</p>
<source><![CDATA[@Dao(config = AppConfig.class)
public interface EmployeeDao {
    @Select
    List<Employee> selectByName(String name);
}]]></source>
				<p>
					コンパイル時のコード生成には次のような利点があります。
				</p>
				<ul>
					<li>実行時に必要なメタ情報をソースコードで記述できるので、リフレクションを使ってメタ情報を構築するフレームワークに比べてパフォーマンスがよい</li>
					<li>ソースコードに記述された通りに動作するので、コンパイル時や実行時にバイトコードエンハンスが行われるコードよりも見通しがよい</li>
					<li>ブレークポイントを設定したりステップ実行をしたりとデバッグがしやすい</li>
				</ul>
			</subsection>
			<subsection name="コンパイル時の規約チェック">
				<p>
					aptを使い、コンパイル時にコードがフレームワークの規約を満たしているかチェックできます。
					たとえば、次のコードをコンパイルすると、<code>update</code>メソッドの部分にエラー表示がされます。
					なぜならば、<code>@Update</code>を注釈したメソッドは更新件数を表す<code>int</code>型の値を返さなければいけないというルールがあるからです。
					エラーは、Eclipseを使っている場合にはエディタに表示され、Antなどでjavacを実行した場合にはAntを実行したコンソールに表示されます。
				</p>
<source><![CDATA[@Dao(config = AppConfig.class)
public interface EmployeeDao {
    @Update
    void update(Employee employee);
}]]></source>
				<p>
					コンパイル時に規約をチェックすることで、わざわざアプリケーションを実行しなくてもエラーに気づくことができます。
				</p>
			</subsection>
			<subsection name="コンパイル時のSQLファイル存在チェックとSQLコメントの文法チェック">
				<p>
					aptを使い、コンパイル時にDaoメソッドに対応するSQLファイルが実際に存在しているかチェックできます。
					たとえば、次のコードをコンパイルすると、<code>selectById</code>メソッドに対応するSQLファイルが存在するかどうかクラスパスの検索が行われます。
				</p>
<source><![CDATA[@Dao(config = AppConfig.class)
public interface EmployeeDao {
    @Select
    Employee selectById(Integer id);
}]]></source>
				<p>
					SQLファイルが存在しない場合は、その時点で<code>selectById</code>メソッドの部分にエラーが表示されます。
					SQLファイルが存在する場合は、続いてSQLコメントの文法チェックが行われます。
				</p>
				<p>
					たとえば、<code>selectById</code>メソッドに対応するSQLファイルが次のようなSQLの場合、エラーが発生します。
					なぜならば、メソッドではパラメータ名が「id」であるのに、SQLコメントでは「employeeId」と記述されているからです。
				</p>
<source><![CDATA[select * from employee where id = /*employeeId*/0]]></source>
				<p>
					コンパイル時にSQLファイルの存在チェックやSQLコメントの文法チェックを行うことで、必ず発生する実行時エラーをコンパイル時に検出できます。
				</p>
			</subsection>
			<subsection name="アプリケーション固有の値型への対応">
				<p>
					アプリケーション固有の値型を作成し、そのクラスをデータベースのテーブルのカラムに対応づけることができます。
					Domaではそのようなクラスを<a href="reference/basic.html">基本型</a>と区別して<a href="reference/domain.html">ドメインクラス</a>と呼んでいます。
					たとえば、電話番号を扱うアプリケーションであれば、<code>PhoneNumber</code>というドメインクラスが作成できるでしょう。
				</p>
<source><![CDATA[@Domain(valueType = String.class)
public class PhoneNumber {

    private final String value;

    public PhoneNumber(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public String getAreaCode() {
       //アプリケーションに固有の振る舞い
       ...
    }
}]]></source>
				<p>
					ドメインクラスには次のような利点があります。
				</p>
				<ul>
					<li>データベース上のカラムの型が同じあってもアプリケーション上意味が異なるものを別のJavaの型で表現できる</li>
					<li>概念をクラスとして明確に表現することでプログラミングをわかりやすくできる</li>
					<li>値と振る舞いを同じクラスで表現できる</li>
				</ul>
			</subsection>
		</section>
	</body>
</document>
