概要
Data Access Object (Dao) はデータベースアクセスのためのインタフェースです。
このページで説明するアノテーションはすべて org.seasar.doma パッケージに属します。
Dao定義
Daoは @Daoが注釈されたインタフェースとして定義します。
インタフェースはトップレベルのインタフェースでなければいけません(他のクラスやインタフェースにネストされていてはいけません)。
インタフェースの実装クラスはaptによりコンパイル時に自動生成されます。
@Dao(config = AppConfig.class)
public interface EmployeeDao {
...
}
@Daoの config要素には、
org.seasar.doma.jdbc.Configの実装クラスを指定しなければいけません。
Configの実装クラスは、データソース、データベースの方言、ネーミング規約等の設定を行います。
クエリ定義
SQLを問い合わせるクエリメソッドには、アノテーションが必須です。 詳細は、クエリを参照してください。
デリゲート定義
Daoは、インタフェースであるためロジックをもつことができません。
しかし、 @Delegateを注釈することで別のクラスに処理を委譲(デリゲート)できます。
この機能は、JDBCのAPIやビルダのAPIを使ってSQLをプログラムで組み立てたい場合に使用するとよいでしょう。
@Dao(config = AppConfig.class)
public interface EmployeeDao {
@Delegate(to = EmployeeDaoDelegate.class)
int execute(Employee employee);
}
@Delegate の to要素には、委譲先のクラスを指定します。
委譲先のクラスのpublicなコンストラクタでは、org.seasar.doma.jdbc.Configを受け取るようにします。
public class EmployeeDaoDelegate {
private Config config;
public EmployeeDaoDelegate(Config config) {
this.config = config;
}
public int execute(Employee employee) {
DataSource dataSource = config.dataSource();
...
}
}
委譲先で委譲元のDaoインスタンスにアクセスしたい場合は、publicなコンストラクタの2番目のパラメータで委譲元のDaoの型を受け取るようにします。
public class EmployeeDaoDelegate {
private Config config;
private EmployeeDao employeeDao;
public EmployeeDaoDelegate(Config config, EmployeeDao employeeDao) {
this.config = config;
this.employeeDao = employeeDao;
}
public int execute(Employee employee) {
...
}
}
委譲先のクラスは次の制約を満たす必要があります。
org.seasar.doma.jdbc.Configを受け取るpublicなコンストラクタを持つ、もしくは、org.seasar.doma.jdbc.Configと委譲元のDaoを受け取るpublicなコンストラクタを持つ- 委譲元のメソッドと同じシグニチャのメソッドを持つ
ビルダを利用したSQLの組み立て
org.seasar.doma.jdbc.builderパッケージでは、プログラムでSQLを組み立てるためのビルダクラスを提供しています。
何らかの理由によりクエリ定義を利用した問い合わせが難しい場合にのみ、これらのビルダクラスを利用することを推奨します。
また、ビルダクラスはデリゲート定義と組み合わせて使用することを推奨します。
検索
検索には、SelectBuilderクラスを使用します。
このクラスのインスタンスは、org.seasar.doma.jdbc.Config型の引数をとるstaticなnewInstanceメソッドで生成できます。
インスタンスには、sqlメソッドでSQL文字列の断片を、paramメソッドでパラメータの型とパラメータを渡せます。
利用例は次のとおりです。
SelectBuilder builder = SelectBuilder.newInstance(config);
builder.sql("select");
builder.sql("id").sql(",");
builder.sql("name").sql(",");
builder.sql("salary");
builder.sql("from Emp");
builder.sql("where");
builder.sql("name like ").param(String.class, "S%");
builder.sql("and");
builder.sql("age > ").param(int.class, 20);
Emp emp = builder.getSingleResult(Emp.class);
組み立てたSQLの実行結果は、getSingleResult、getResultList、iterateのメソッドで処理できます。
それぞれ、1件を処理したい場合、複数件を処理したい場合、複数件を1件ずつ処理したい場合に使用します。
挿入
挿入には、InsertBuilderクラスを使用します。
このクラスのインスタンスは、org.seasar.doma.jdbc.Config型の引数をとるstaticなnewInstanceメソッドで生成できます。
インスタンスには、sqlメソッドでSQL文字列の断片を、paramメソッドでパラメータの型とパラメータを渡せます。
InsertBuilder builder = InsertBuilder.newInstance(config);
builder.sql("insert into Emp");
builder.sql("(name, salary)");
builder.sql("values (");
builder.param(String.class, "SMITH").sql(", ");
builder.param(BigDecimal.class, new BigDecimal(1000)).sql(")");
builder.execute();
組み立てたSQLはexecuteメソッドで実行できます。
更新
更新には、UpdateBuilderクラスを使用します。
このクラスのインスタンスは、org.seasar.doma.jdbc.Config型の引数をとるstaticなnewInstanceメソッドで生成できます。
インスタンスには、sqlメソッドでSQL文字列の断片を、paramメソッドでパラメータの型とパラメータを渡せます。
UpdateBuilder builder = UpdateBuilder.newInstance(config);
builder.sql("update Emp");
builder.sql("set");
builder.sql("name = ").param(String.class, "SMIHT").sql(",");
builder.sql("salary = ").param(BigDecimal.class, new BigDecimal("1000"));
builder.sql("where");
builder.sql("id = ").param(int.class, 10);
builder.execute();
組み立てたSQLはexecuteメソッドで実行できます。
削除
削除には、DeleteBuilderクラスを使用します。
このクラスのインスタンスは、org.seasar.doma.jdbc.Config型の引数をとるstaticなnewInstanceメソッドで生成できます。
インスタンスには、sqlメソッドでSQL文字列の断片を、paramメソッドでパラメータの型とパラメータを渡せます。
DeleteBuilder builder = DeleteBuilder.newInstance(config);
builder.sql("delete from Emp");
builder.sql("where");
builder.sql("name = ").param(String.class, "SMITH");
builder.sql("and");
builder.sql("salary = ").param(BigDecimal.class, new BigDecimal(1000));
builder.execute();
組み立てたSQLはexecuteメソッドで実行できます。
Daoの利用方法
コンパイルすると、aptにより実装クラスが生成されます。 実装クラスをインスタンス化して使用してください。 ただし、設定クラスをDIコンテナで管理する場合は、Daoのインスタンス化はアプリケーションのコードで行わずDIコンテナで制御してください。
EmployeeDao employeeDao = new EmployeeDaoImpl(); Employee employee = employeeDao.selectById(1);
デフォルトでは、実装クラスの名前はインタフェースの名前にImplをサフィックスしたものになります。
パッケージやサフィックスを変更するには、アノテーション処理を参照してください。
デフォルトコンストラクタを使用した場合は、@Daoの config要素に
指定した設定によりjavax.sql.DataSourceが決定されますが、
特定の DataSourceを指定してインスタンス化することも可能です。
DataSource dataSource = ...; EmployeeDao employeeDao = new EmployeeDaoImpl(dataSource); Employee employee = employeeDao.selectById(1);
また、同様にjava.sql.Connectionを指定してインスタンス化することも可能です。
Connection connection = ...; EmployeeDao employeeDao = new EmployeeDaoImpl(connection); Employee employee = employeeDao.selectById(1);
DataSourceやConnectionをコンストラクタに指定してインスタンス化する方法は、
JDBCを直接利用した既存のアプリケーションで利用するのに適しています。
Daoインタフェースはエンティティクラスと1対1で結びついているわけではありません。 ひとつのDaoインタフェースで複数のエンティティクラスを扱えます。
@Dao(config = AppConfig.class)
public interface MyDao {
@Select
Employee selectEmployeeById(int id);
@Select
Department selectDepartmentByName(String name);
@Update
int updateAddress(Address address);
}
