About

ドキュメント

Javadoc

モジュール

プロジェクト文書

Built by Maven

SQL自動生成による操作

検索

複数件検索

複数件を検索する場合は、 gerResultList() を使います。

List<Employee> results = 
    jdbcManager
        .from(Employee.class)
        .getResultList();

検索するエンティティは、 from() で指定します。

デフォルトでは、結果がなかった場合は、 空の List が返されます。 disallowNoResult() を呼び出すと、 結果がなかった場合は javax.persistence.NoResultException が発生します。

List<Employee> results = 
    jdbcManager
        .from(Employee.class)
        .disallowNoResult()
        .getResultList();

1件検索

1件検索する場合は、 getSingleResult() を使います。

Employee result = 
    jdbcManager
        .from(Employee.class)
        .getSingleResult();

結果が複数件になる場合は、 javax.persistence.NonUniqueResultException が発生します。

Employee result = 
    jdbcManager
        .from(Employee.class)
        .where("id = ?", id)
        .getSingleResult();

デフォルトでは、結果がなかった場合は、 null が返されます。 disallowNoResult() を呼び出すと、 結果がなかった場合は javax.persistence.NoResultException が発生します。

Employee result = 
    jdbcManager
        .from(Employee.class)
        .where("id = ?", id)
        .disallowNoResult()
        .getSingleResult();

イテレーションによる検索

検索結果が多くの行を返すため、 List でまとめて受け取ることが困難な場合は iterate(IterationCallback) を使います。

int results = 
    jdbcManager
        .from(Employee.class)
        .iterate(
            new IterationCallback<BeanMap, Integer>() {
                int count;
                public Integer iterate(BeanMap map, IterationContext context) {
                    if (...) {
                        ++count;
                    }
                    return count;
                }
            });

iterate(IterationCallback) の引数には、 次のインターフェースを実装したクラスのインスタンスを渡します。

  • org.seasar.extension.jdbc.IterationCallback<ENTITY, RESULT>

ENTITYfrom() で指定したエンティティクラス、 RESULTiterate(IterationCallback) が返す結果の型を指定します。

from() で指定したエンティティ1件ごとに次のメソッドがコールバックされます。

  • RESULT iterate(ENTITY entity, IterationContext context)

コールバックメソッドが最後に返した値が iterate(IterationCallback) の戻り値となります。

コールバックメソッドの第2引数で渡される org.seasar.extension.jdbc.IterationContext exit プロパティを true にすると、 問い合わせ結果のイテレーションは終了となり、 検索結果の残りは無視されます。 その時の戻り値が iterate(IterationCallback) の戻り値となります。

1対多関連を 結合 する場合は、 from() で指定したエンティティで ソート して、結果セットが次のような順になるようにします。

from() で指定したエンティティ 結合したエンティティ
A1 B1
A1 B2
A2 B1
A2 B2

上記のような結果セットの場合、 コールバックメソッドはA1とA2が1回ずつ、 計2回呼び出されます。 A1に関連づけられたB1およびB2のインスタンスと、 A2に関連づけられたB1およびB2のインスタンスは異なります(同じ値を持つが同一ではない)。

from() で指定したエンティティ 結合したエンティティ
A1 B1
A2 B1
A1 B2
A2 B2

結果セットが上記のような順になっている場合、 コールバックメソッドは4回呼び出されてしまいます。

検索結果の行数取得

SELECT COUNT(*) ~ による検索結果の行数を取得する場合は、 getCount() を使います。

long count = 
    jdbcManager
        .from(Employee.class)
        .getCount();
注意点

getCount() が返す値は問い合わせ結果の行数であり、 同等の問い合わせを行った場合に getResultList() が返すエンティティの数と一致するとは限りません。 from() で指定したエンティティに 1対多関連結合 した場合、 getCount() が返す行数は getResultList() が返すエンティティの数よりも多くなる場合があります。

結合

他のエンティティを結合する場合は、次のメソッドを使用します。

  • innerJoin(CharSequence name)
  • innerJoin(CharSequence name, boolean fetch)
  • leftOuterJoin(CharSequence name)
  • leftOuterJoin(CharSequence name, boolean fetch)

第1引数は、結合したいエンティティのプロパティ名です。

List<Employee> results = 
    jdbcManager
        .from(Employee.class)
        .innerJoin("department")
        .getResultList();

次のように外部結合にすることもできます。

List<Employee> results = 
    jdbcManager
        .from(Employee.class)
        .leftOuterJoin("department")
        .getResultList();

検索条件には含めたいけど、検索結果には含めたくない場合、 2番名の引数をfalseにします。

List<Employee> results = 
    jdbcManager
        .from(Employee.class)
        .innerJoin("department", false)
        .where("department.name = 'RESEARCH'")
        .getResultList();

結合条件の追加

追加の結合条件を指定することもできます。

追加の結合条件をSQL文字列で指定する場合は、次のメソッドを使用します。

  • innerJoin(CharSequence name, String condition, Object... params)
  • innerJoin(CharSequence name, boolean fetch, String condition, Object... params)
  • leftOuterJoin(CharSequence name, String condition, Object... params)
  • leftOuterJoin(CharSequence name, boolean fetch, String condition, Object... params)

引数 condition に指定できる条件は、SQLと同じです。 SQLとの違いは、カラム名の代わりにプロパティ名を書くことです。 関連先のプロパティを指定する場合は、 innerJoin()/leftOuterJoin() で指定した名前. プロパティ名になります。

List<Department> results = 
    jdbcManager
        .from(Department.class)
        .leftOuterJoin(
            "employee", 
            "employee.salary > ?", 
            1000)
        .getResultList();

指定方法の詳細は「 SQL文字列による指定 」を参照してください。

追加の結合条件を SimpleWhere で指定する場合は、次のメソッドを使用します。

  • innerJoin(CharSequence name, Where condition)
  • innerJoin(CharSequence name, Where... conditions)
  • innerJoin(CharSequence name, boolean fetch, Where condition)
  • innerJoin(CharSequence name, boolean fetch, Where... conditions)
  • leftOuterJoin(CharSequence name, Where condition)
  • leftOuterJoin(CharSequence name, Where... conditions)
  • leftOuterJoin(CharSequence name, boolean fetch, Where condition)
  • leftOuterJoin(CharSequence name, boolean fetch, Where... conditions)
List<Department> results = 
    jdbcManager
        .from(Department.class)
        .leftOuterJoin(
            "employee", 
            new SimpleWhere().gt("employee.salary", 1000))
        .getResultList();

指定方法の詳細は「 SimpleWhereによる指定 」を参照してください。

結合のネスト

結合は、employee.addressのようにネストすることもできます。 ネストする場合は、必ずベースとなる結合を先に指定します。 employee.addressの場合、employeeがベースとなる結合です。

List<Department> results = 
    jdbcManager
        .from(Department.class)
        .leftOuterJoin("employee")
        .leftOuterJoin("employee.address")
        .getResultList();

結合は、多対一関連、一対多関連、一対一関連のどれでも可能で、 いくつでもネストすることが可能です。

検索条件

IDとバージョンによる指定

IDプロパティ (主キー) を指定して検索対象を指定する場合は、 id(Object...) を使います。 引数はエンティティに定義されたIDプロパティと同じ数・同じ並びで指定します。

jdbcManager
    .from(Department.class)
    .id(100)
    .getSingleResult();

IDと同時にバージョンを指定することもできます。 バージョンプロパティを指定する場合は、 version(Object) を使います。

jdbcManager
    .from(Department.class)
    .id(100)
    .version(10)
    .getSingleResult();

IDを指定しないでバージョンだけを指定することはできません。

SQL文字列による指定

より複雑な検索条件を指定する場合は、 where(String criteria, Object... params) を使います。 where(String criteria, Object... params) に書くことのできる条件は、SQLと同じです。 SQLとの違いは、カラム名の代わりにプロパティ名を書くことです。 関連先のプロパティを指定する場合は、 innerJoin()/leftOuterJoin() で指定した名前.プロパティ名になります。

jdbcManager
    .from(Department.class)
    .leftOuterJoin("employeeList")
    .leftOuterJoin("employeeList.address")
    .where("employeeList.salary between ? and ? and employeeList.address.street like ?", ...)
    .getResultList();

java.util.Datejava.util.Calendar 型のパラメータを指定する場合は、時制を指定することができます。 時制の指定は org.seasar.extension.jdbc.parameter.Parameter のstaticメソッドを使います。

date(Date) または date(Calendar)
パラメータをSQL標準のDATE型 (日付のみ) として扱います。
time(Date) または time(Calendar)
パラメータをSQL標準のTIME型 (時刻のみ) として扱います。
timestamp(Date) または timestamp(Calendar)
パラメータをSQL標準のTIMESTAMP型 (日付と時刻) として扱います。
import static org.seasar.extension.jdbc.parameter.Parameter.*;

jdbcManager
    .from(Employee.class)
    .where("heredate = ?", date(heredate))
    .getResultList();

byte[]String 型のパラメータを指定する場合は、ラージオブジェクトであることを指定することができます。 ラージオブジェクトの指定は org.seasar.extension.jdbc.parameter.Parameter のstaticメソッドを使います。

lob(String)
パラメータをCLOBとして扱います。
lob(byte[]) または lob(Serializable)
パラメータをBLOBとして扱います。
import static org.seasar.extension.jdbc.parameter.Parameter.*;

jdbcManager
    .from(Employee.class)
    .where("largeName = ?", lob(largeName))
    .getResultList();

SimpleWhereによる指定

検索条件の入力画面などでは、ユーザの入力があった部分をandでつないで、 条件を組み立てるということが良く行われます。 このようなケースを簡単に処理するために、 SimpleWhereとMapでも、検索条件を指定できるようにしています。

名前、仕事タイプ、給与の上限下限を条件に検索する画面を考えてみましょう。 べたに検索条件を組み立てるとはこんな感じになるはずです。

public String departmentName;
public String[] jobTypes = new String[0];
public BigDecimal salaryMax;
public BigDecimal salaryMin;
...
StringBuilder sb = new StringBuilder(100);
boolean found = false;
List<Object> values = new ArrayList<Object>();
if (departmentName != null) {
    sb.append("department.name = ?");
    values.add(departmentName);
    found = true;
}
if (jobTypes.length > 0) {
    if (found) {
        sb.append(" and ");
    }
    sb.append("jobType in (");
    for (JobType jt : jobTypes) {
        sb.append("?, ");
        values.add(jt);
    }
    sb.setLength(sb.length() - 2);
    sb.append(")");
    found = true;
}
if (salaryMin != null) {
    if (found) {
        sb.append(" and ");
    }
    sb.append("salary >= ?");
    values.add(salaryMin);
    found = true;
}
if (salaryMax != null) {
    if (found) {
        sb.append(" and ");
    }
    sb.append("salary <= ?");
    values.add(salaryMax);
    found = true;
}
jdbcManager
    .from(Employee.class)
    .where(sb.toString(), values.toArray())
    .getResultList();

SimpleWhereを使って組み立てれば、こんなに簡単になります。

public String departmentName;
public String[] jobTypes = new String[0];
public BigDecimal salaryMax;
public BigDecimal salaryMin;
...
jdbcManager
    .from(Employee.class)
    .where(
        new SimpleWhere()
            .eq("department.name", departmentName)
            .in("jobType", jobTypes)
            .ge("salary", salaryMin)
            .le("salary", salaryMax))
    .getResultList();

SimpleWhereには次のメソッドがあります。

メソッド 説明
eq(CharSequence propertyName, Object value) propertyName = ? の条件を追加します。valueがnullの時は追加されません。
ne(CharSequence propertyName, Object value) propertyName <> ? の条件を追加します。valueがnullの時は追加されません。
lt(CharSequence propertyName, Object value) propertyName < ? の条件を追加します。valueがnullの時は追加されません。
le(CharSequence propertyName, Object value) propertyName <= ? の条件を追加します。valueがnullの時は追加されません。
gt(CharSequence propertyName, Object value) propertyName > ? の条件を追加します。valueがnullの時は追加されません。
ge(CharSequence propertyName, Object value) propertyName >= ? の条件を追加します。valueがnullの時は追加されません。
in(CharSequence propertyName, Object... values) propertyName in (?, ...) の条件を追加します。 valuesがnullの時または配列の長さが0の時は追加されません。
in(CharSequence propertyName, Collection<?> values) propertyName in (?, ...) の条件を追加します。 valuesがnullの時またはリストの長さが0の時は追加されません。
notIn(CharSequence propertyName, Object... values) propertyName not in (?, ...) の条件を追加します。 valuesがnullの時または配列の長さが0の時は追加されません。
notIn(CharSequence propertyName, Collection<?> values) propertyName not in (?, ...) の条件を追加します。 valuesがnullの時またはリストの長さが0の時は追加されません。
like(CharSequence propertyName, String value) propertyName like ? の条件を追加します。 valueがnullの時は追加されません。
like(CharSequence propertyName, String value, char escape) propertyName like ? escape ? の条件を追加します。 valueがnullの時は追加されません。
notLike(CharSequence propertyName, String value) propertyName not like ? の条件を追加します。 valueがnullの時は追加されません。
notLike(CharSequence propertyName, String value, char escape) propertyName not like ? escape ? の条件を追加します。 valueがnullの時は追加されません。
starts(CharSequence propertyName, String value) propertyName like ? の条件を追加します。 valueがnullの時は追加されません。 valueの最後に自動的に % が追加されます。 valueに '%', '_' が含まれる場合はエスケープされます。
notStarts(CharSequence propertyName, String value) propertyName not like ? の条件を追加します。 valueがnullの時は追加されません。 valueの最後に自動的に % が追加されます。 valueに '%', '_' が含まれる場合はエスケープされます。
ends(CharSequence propertyName, String value) propertyName like ? の条件を追加します。 valueがnullの時は追加されません。 valueの最初に自動的に % が追加されます。 valueに '%', '_' が含まれる場合はエスケープされます。
notEnds(CharSequence propertyName, String value) propertyName not like ? の条件を追加します。 valueがnullの時は追加されません。 valueの最初に自動的に % が追加されます。 valueに '%', '_' が含まれる場合はエスケープされます。
contains(CharSequence propertyName, String value) propertyName like ? の条件を追加します。 valueがnullの時は追加されません。 valueの最初と最後に自動的に % が追加されます。 valueに '%', '_' が含まれる場合はエスケープされます。
notContains(CharSequence propertyName, String value) propertyName not like ? の条件を追加します。 valueがnullの時は追加されません。 valueの最初と最後に自動的に % が追加されます。 valueに '%', '_' が含まれる場合はエスケープされます。
isNull(CharSequence propertyName, Boolean value) propertyName is null の条件を追加します。 valueがnullあるいはBoolean.FALSEの時は追加されません。
isNotNull(CharSequence propertyName, Boolean value) propertyName is not null の条件を追加します。 valueがnullあるいはBoolean.FALSEの時は追加されません。
excludesWhitespace() valueが空白文字列の時は条件に追加されません。

Mapによる指定

Mapを使うと次のようになります。

public String departmentName;
public String[] jobTypes = new String[0];
public BigDecimal salaryMax;
public BigDecimal salaryMin;
...
Map<String, Object> w = new HashMap<String, Object>();
w.put("department.name", departmentName);
w.put("jobType_IN", jobTypes);
w.put("salary_LE", salaryMax);
w.put("salary_GE", salaryMin);
jdbcManager
    .from(Employee.class)
    .where(w)
    .getResultList();

org.seasar.extension.jdbc.parameter.Parameter のstaticメソッドを使うと、流れるようなインタフェースでMapを組み立てることも出来ます。

import static org.seasar.extension.jdbc.parameter.Parameter.*;

jdbcManager
    .from(Employee.class)
    .where(
        params("department.name", departmentName)
            .$("jobType_IN", jobTypes)
            .$("salary_LE", salaryMax)
            .$("salary_GE", salaryMin)
            .$())
   .getResultList();

マップのキーにプロパティ名_サフィックスを指定します。 サフィックスがない場合は、 _EQ が指定されたとみなされます。

次のサフィックスを使うことができます。

サフィックス 説明
_EQ propertyName = ? の条件を追加します。valueがnullの時は追加されません。
_NE propertyName <> ? の条件を追加します。valueがnullの時は追加されません。
_LT propertyName < ? の条件を追加します。valueがnullの時は追加されません。
_LE propertyName <= ? の条件を追加します。valueがnullの時は追加されません。
_GT propertyName > ? の条件を追加します。valueがnullの時は追加されません。
_GE propertyName >= ? の条件を追加します。valueがnullの時は追加されません。
_IN propertyName in (?, ...) の条件を追加します。 値は配列または java.util.Collection をサポートしています。 valueがnullの時または長さが0の時は追加されません。
_NOT_IN propertyName not in (?, ...) の条件を追加します。 値は配列または java.util.Collection をサポートしています。 valueがnullの時または長さが0の時は追加されません。
_LIKE propertyName like ? の条件を追加します。 valueがnullの時は追加されません。
_NOT_LIKE propertyName not like ? の条件を追加します。 valueがnullの時は追加されません。
_STARTS propertyName like ? の条件を追加します。 valueがnullの時は追加されません。 valueの最後に自動的に % が追加されます。
_NOT_STARTS propertyName not like ? の条件を追加します。 valueがnullの時は追加されません。 valueの最後に自動的に % が追加されます。
_ENDS propertyName like ? の条件を追加します。 valueがnullの時は追加されません。 valueの最初に自動的に % が追加されます。
_NOT_ENDS propertyName not like ? の条件を追加します。 valueがnullの時は追加されません。 valueの最初に自動的に % が追加されます。
_CONTAINS propertyName like ? の条件を追加します。 valueがnullの時は追加されません。 valueの最初と最後に自動的に % が追加されます。
_NOT_CONTAINS propertyName not like ? の条件を追加します。 valueがnullの時は追加されません。 valueの最初と最後に自動的に % が追加されます。
_IS_NULL propertyName is null の条件を追加します。 valueがnullあるいはBoolean.FALSEの時は追加されません。 値はBooleanのみをサポートしています。
_IS_NOT_NULL propertyName is not null の条件を追加します。 valueがnullあるいはBoolean.FALSEの時は追加されません。 値はBooleanのみをサポートしています。

マップの組み立てを手動でやる必要は、基本的にありません。 なぜなら、 SimpleWhere のほうが便利だからです。 マップを使う場合は、次のように org.seasar.framework.beans.util.Beans を使います。

createAndCopy(Class<T> destClass, Object src) の第一引数には、 BeanMap.class を指定します。 BeanMapMap<String, Object> なクラスで、 存在しないキーにアクセスすると 例外が発生します。 キーの値は、 AAA_BBB のような '_' 記法の値をを aaaBbb のようなキャメル記法に変換したものです。 第二引数にはコピー元になるオブジェクトを指定します。

prefix(String prefix) の引数には、プロパティ名のプレフィックスを指定します。 プレフィックスを指定した場合、プレフィックスを持つプロパティだけが対象になります。 プロパティ名がマップのキーに変換されるときに、 プレフィックスは削除され、'$'は'.'に変換されます。

public String where_department$name;
public String[] where_jobType_IN = new String[0];
public BigDecimal where_salary_LE;
public BigDecimal where_salary_GE;
...
jdbcManager
    .from(Employee.class)
    .where(
        Beans
            .createAndCopy(BeanMap.class, this)
            .prefix("where_")
            .execute())
    .getResultList();

ソート順

ソート順を指定する場合は、 orderBy() を使います。 orderBy() に書くことのできる条件は、SQLと同じです。 SQLとの違いは、カラム名の代わりにプロパティ名を書くことです。 関連先のプロパティを指定する場合は、 innerJoin()/leftOuterJoin() で指定した名前.プロパティ名になります。

jdbcManager
    .from(Employee.class)
    .leftOuterJoin("department")
    .orderBy("name, department.name")
    .getResultList();

orderBy(OrderByItem... orderByItems) を使うこともできます。 OrderByItems はソート順のキーとなるプロパティ名と昇順または降順を示すもので、 org.seasar.extension.jdbc.operation.Operations のメソッド asc(CharSequence propertyName) および desc(CharSequence propertyName) を使って次のように指定することができます。

jdbcManager
    .from(Employee.class)
    .leftOuterJoin("department")
    .orderBy(
        asc("name"), 
        desc("department.name"))
    .getResultList();

排他制御

SELECT時にロックを取得する場合は、

  • forUpdate()
  • forUpdate(CharSequence... propertyNames)
  • forUpdateNowait()
  • forUpdateNowait(CharSequence... propertyNames)
  • forUpdateWait(int seconds)
  • forUpdateWait(int seconds, CharSequence... propertyNames)

を使います。 全てのRDBMSでこれらの操作が利用できるわけではありません。 サポートされていないメソッドを呼び出すと UnsupportedOperationException がスローされます。

forUpdate(String...)forUpdateNowait(String...) の第1引数および forUpdateWait(int, String...) の第2引数には、ロック対象となるプロパティ名を指定します。

forUpdateWait(int)forUpdateWait(int, String...) の第1引数では、ロックを獲得できるまでの最大待機時間を秒単位で指定します。

以下の例では、EmployeeDepartmentを結合していて、 ロック対象のプロパティが明示されていないので、両テーブルのロックが取得されます。

jdbcManager
    .from(Employee.class)
    .leftOuterJoin("department")
    .where("department.name = ?", deptName)
    .forUpdate()
    .getResultList();

以下の例でもEmployeeDepartmentを結合していますが、 指定されたプロパティを持つEmployeeのロックのみが取得されます。

jdbcManager
    .from(Employee.class)
    .leftOuterJoin("department")
    .where("department.name = ?", deptName)
    .forUpdate("id")
    .getResultList();

排他制御とページングを組み合わせることはできません。

指定したプロパティのみを検索結果に含める

指定したプロパティのみを検索結果に含める場合は、 includes() を使います。 ただし、 @Id アノテーションが付けられたプロパティは無条件で検索結果に含まれます。 不要なプロパティを検索結果から除外することで、 データベースから転送されるデータ量やJVMのメモリ使用量を減らすことができます。

Employee result = 
    jdbcManager
        .from(Employee.class)
        .where("id = ?", id)
        .includes("id", "name")
        .getSingleResult();

次のように結合するエンティティのプロパティを指定することもできます。

List<Employee> results = 
    jdbcManager
        .from(Employee.class)
        .leftOuterJoin("department")
        .leftOuterJoin("department.address")
        .includes("id", "name", "department.name", "department.address.id")
        .getResultList();

結合するエンティティへの関連プロパティを指定した場合、 関連先のエンティティが持つプロパティはすべて検索結果に含まれます。 ただし、関連先のエンティティが持つプロパティが excludes() に指定された場合、そのプロパティは検索結果から除外されます。

次の例では、関連プロパティ departmentincludes() に指定されているため、 Department エンティティの持つ各プロパティが取得されます。 ただし、 excludes()department.name が指定されているため、 Departmentname プロパティは取得されません。

List<Employee> results = 
    jdbcManager
        .from(Employee.class)
        .leftOuterJoin("department")
        .leftOuterJoin("department.address")
        .includes("id", "name", "department")
        .excludes("department.name")
        .getResultList();
注意点

フェッチ対象外定義 を指定したプロパティを includes() に指定すると、そのプロパティを eager() で指定していなくても検索結果に含まれます。

ただし、 フェッチ対象外定義 を指定したプロパティそのものではなく、そのプロパティを含むエンティティへの関連プロパティを includes() に指定した場合は、その関連先エンティティに含まれている フェッチ対象外定義 のプロパティは、 eager() で指定されたものだけが検索結果に含まれます。

注意点

includes() または excludes() を指定して取得したインスタンスを更新に使用する場合、 更新時に同様の includes() を指定しないと検索結果に含めなかったカラムがすべて空の値で更新されます。 excludesNull()changedFrom() を指定して更新対象外にすることも可能です。

指定したプロパティを検索結果から除外する

指定したプロパティを検索結果から除外する場合は、 excludes() を使います。 ただし、 @Id アノテーションが付けられたプロパティは無条件で検索結果に含まれます。 不要なプロパティを検索結果から除外することで、 データベースから転送されるデータ量やJVMのメモリ使用量を減らすことができます。 includes() に同じプロパティを指定した場合、 includes() の指定が優先されます。

Employee result = 
    jdbcManager
        .from(Employee.class)
        .where("id = ?", id)
        .excludes("id", "name")
        .getSingleResult();

次のように結合するエンティティのプロパティを指定することもできます。

List<Employee> results = 
    jdbcManager
        .from(Employee.class)
        .leftOuterJoin("department")
        .leftOuterJoin("department.address")
        .excludes("id", "name", "department.name", "department.address.id")
        .getResultList();

次のように結合するエンティティへの関連プロパティを指定した場合、 関連先のエンティティが持つプロパティはすべて検索結果から除外されます。

List<Employee> results = 
    jdbcManager
        .from(Employee.class)
        .leftOuterJoin("department")
        .leftOuterJoin("department.address")
        .excludes("id", "name", "department")
        .getResultList();
注意点

フェッチ対象外定義 を指定したプロパティや、そのプロパティを含むエンティティへの関連プロパティを excludes() に指定すると、そのプロパティを eager() で指定していても検索結果には含まれません。

注意点

includes() または excludes() を指定して取得したインスタンスを更新に使用する場合、 更新時に同様の includes() または excludes() を指定しないと検索結果に含めなかったカラムがすべて空の値で更新されます。 excludesNull()changedFrom() を指定して更新対象外にすることも可能です。

指定したプロパティをフェッチ対象にする

フェッチ対象外定義 を指定したプロパティをフェッチ対象にする (検索結果に含む) には、 eager(CharSequence... propertyNames) を使います。 関連先のプロパティを指定する場合は、 innerJoin()/leftOuterJoin() で指定した名前.プロパティ名になります。

List<Employee> results = 
    jdbcManager
        .from(Employee.class)
        .eager("largeDto")
        .getResultList();
注意点

eager()includes() は、同時に使わないことを推奨します。

フェッチ対象外定義 が指定されたプロパティを includes() に指定すると、そのプロパティを eager() で指定しなくても検索結果に含まれます。 そのため、 includes() を使う場合は eager() を使う必要はありません。

注意点

eager() は、 フェッチ対象外定義 の指定を打ち消す効果があります。その後で includes() / excludes() が適用されます。

フェッチ対象外定義 を指定したプロパティを eager() に指定しても、 includes() の指定がある場合は、そのプロパティまたは、そのプロパティを含むエンティティへの関連プロパティが includes() に含まれていないと検索結果には含まれません。

フェッチ対象外定義 を指定したプロパティを eager() に指定しても、そのプロパティまたは、そのプロパティを含むエンティティへの関連プロパティが excludes() に含まれていると検索結果には含まれません。

ページング

ページングを指定する場合は、 limit(), offset() を使います。 limit() には、取得する行数を指定します。 offset() には、最初に取得する行の位置を指定します。 最初の行の位置は0になります。 ページングを指定するには、必ず ソート順 の指定も必要です。

jdbcManager
    .from(Employee.class)
    .orderBy("name")
    .limit(100)
    .offset(10)
    .getResultList();

排他制御とページングを組み合わせることはできません。

limit() で指定する値は問い合わせ結果の行数であり、 getResultList() が返すエンティティの数と一致するとは限りません。 from() で指定したエンティティに 1対多関連結合 した場合、 getResultList() が返すエンティティの数は limit() で指定した数よりも少なくなる場合があります。

最大行数

最大行数を指定する場合は、 maxRows() を使います。 最大行数を超える行は、通知なしに除外されます。

jdbcManager
    .from(Employee.class)
    .maxRows(1000)
    .getResultList();

フェッチサイズ

フェッチサイズを指定する場合は、 fetchSize() を使います。

jdbcManager
    .from(Employee.class)
    .fetchSize(100)
    .getResultList();

クエリタイムアウト

クエリタイムアウト(秒)を指定する場合は、 queryTimeout() を使います。

jdbcManager
    .from(Employee.class)
    .queryTimeout(10)
    .getResultList();

ヒント

コメントによるヒントを指定する場合は、 hint() を使います。

jdbcManager
    .from(Employee.class)
    .hint("INDEX(Employee IDX1)")
    .getResultList();

ヒント中のエンティティ名(上記例では Employee )は別名に置換され、 Oracleでは次のようなコメントがSQLに含まれます。

/*+ INDEX(T1_ IDX1) */

ヒント中の関連プロパティ名も別名に置換されます。

jdbcManager
    .from(Employee.class)
    .leftOuterJoin("department")
    .hint("INDEX(department IDX2)")
    .getResultList();

上記の場合、 Oracleでは次のようなコメントがSQLに含まれます。

/*+ INDEX(T2_ IDX2) */

コメントによるヒントをサポートしていないRDBMSの場合、 hint() は無視され、 SQLにコメントは付加されません。

挿入

1件挿入

エンティティを挿入する場合は、 insert()execute() を組み合わせます。

int count = 
    jdbcManager
        .insert(employee)
        .execute();

引数はエンティティで、戻り値は、更新した行数です。 挿入するときに、識別子を自動設定することができます。 詳しくは、 識別子定義 を参照してください。

一意制約違反によりエンティティ挿入ができなかった場合は、 javax.persistence.EntityExistsException が発生します。

バッチ挿入

複数のエンティティをバッチ挿入する場合は、 insertBatch()execute() を組み合わせます。

int[] countArray = 
    jdbcManager
        .insertBatch(employees)
        .execute();

引数はエンティティのリストあるいは配列(可変長引数)で、戻り値は、更新した行数の配列です。 挿入するときに、識別子を自動設定することができます。 詳しくは、 識別子定義 を参照してください。

一意制約違反によりエンティティを挿入ができなかった場合は、 javax.persistence.EntityExistsException が発生します。

nullの項目を挿入しない

挿入の対象からnullの項目を除外する場合は、 excludesNull() を使います。 バッチ系の挿入は、すべてのエンティティに同じSQLを適用しなければならないので、 null を除外してバッチ挿入することはできません。 なぜなら、すべてのエンティティの null の項目が同じだとは限らないからです。

int count = 
    jdbcManager
        .insert(employee)
        .excludesNull()
        .execute();

指定したプロパティのみを挿入対象にする

指定したプロパティのみを挿入対象にする場合は、 includes() を使います。

int count = 
    jdbcManager
        .insert(employee)
        .includes("id", "name")
        .execute();

指定したプロパティを挿入対象から除外する

指定したプロパティを挿入対象から除外する場合は、 excludes() を使います。

int count = 
    jdbcManager
        .insert(employee)
        .excludes("version")
        .execute();

バッチ挿入のサイズを指定する

バッチ挿入のサイズを設定するには batchSize() を使います。

int[] countArray = 
    jdbcManager
        .insertBatch(employees)
        .batchSize(50)
        .execute();

更新

1件更新

エンティティを更新する場合は、 update()execute() を組み合わせます。

int count = 
    jdbcManager
        .update(employee)
        .execute();

引数はエンティティで、戻り値は、更新した行数です。 更新するときに、バージョンによる楽観的排他制御をすることができます。 詳しくは、 バージョン定義 を参照してください。

注意点

識別子定義 のないエンティティは、 SQL自動生成による更新は出来ません。

バッチ更新

複数のエンティティをバッチ更新する場合は、 updateBatch()execute() を組み合わせます。

int[] countArray = 
    jdbcManager
        .updateBatch(employees)
        .execute();

引数はエンティティのリストあるいは配列(可変長引数)で、戻り値は、更新した行数の配列です。 更新するときに、バージョンによる楽観的排他制御をすることができます。 詳しくは、 バージョン定義 を参照してください。

注意点

識別子定義 のないエンティティは、 SQL自動生成によるバッチ更新は出来ません。

バージョンプロパティを通常の更新対象にする

バージョンプロパティを通常の更新対象に含め、バージョンチェックの対象外にする場合は、 includesVersion() を使います。

int count = 
    jdbcManager
        .update(employee)
        .includesVersion()
        .execute();

nullの項目を更新しない

更新の対象からnullの項目を除外する場合は、 excludesNull() を使います。 バッチ系の更新は、すべてのエンティティに同じSQLを適用しなければならないので、 null を除外してバッチ更新することはできません。 なぜなら、すべてのエンティティの null の項目が同じだとは限らないからです。

int count = 
    jdbcManager
        .update(employee)
        .excludesNull()
        .execute();

指定したプロパティのみを更新対象にする

指定したプロパティのみを更新対象にする場合は、 includes() を使います。

int count = 
    jdbcManager
        .update(employee)
        .includes("id", "name")
        .execute();

指定したプロパティを更新対象から除外する

指定したプロパティを更新対象から除外する場合は、 excludes() を使います。

int count = 
    jdbcManager
        .updateBatch(employees)
        .excludes("version")
        .execute();

変更のあったプロパティのみを更新対象にする

変更のあったプロパティのみを更新対象にする場合は、 changedFrom() を使います。バッチ系の更新は、すべてのエンティティに同じSQLを適用しなければならないので、 変更のあったプロパティのみをバッチ更新することはできません。 なぜなら、変更のあったプロパティがすべてのエンティティで同じだとは限らないからです。 最初の引数は、変更前の状態を持ったエンティティもしくはマップです。

Employee before = ...;
int count = 
    jdbcManager
        .update(employee)
        .changedFrom(before)
        .execute();

JdbcManager#update() に渡されたエンティティと, changedFrom() に渡されたエンティティまたはマップに相違がない場合、SQLは実行されず、 execute() の戻り値の更新行数として0が返されます。

更新行数をチェックしない

バージョンによる楽観的排他制御を行う場合、 更新できた行数が0だと javax.persistence.OptimisticLockException が発生します。 更新行数を正しく返さないJDBCドライバを使用する場合は、 suppresOptimisticLockException() を呼び出すことで、更新できた行数のチェックを行わなくなります。

int[] countArray = 
    jdbcManager
        .updateBatch(employees)
        .suppresOptimisticLockException()
        .execute();

バッチ更新のサイズを指定する

バッチ更新のサイズを設定するには batchSize() を使います。

int[] countArray = 
    jdbcManager
        .updateBatch(employees)
        .batchSize(50)
        .execute();

削除

1件削除

エンティティを削除する場合は、 delete()execute() を組み合わせます。

int count = 
    jdbcManager
        .delete(employee)
        .execute();

引数はエンティティで、戻り値は、更新した行数です。 削除するときに、バージョンによる楽観的排他制御をすることができます。 詳しくは、 バージョン定義 を参照してください。

注意点

識別子定義 のないエンティティは、 SQL自動生成による削除は出来ません。

バッチ削除

複数のエンティティをバッチ削除する場合は、 deleteBatch()execute() を組み合わせます。

int[] countArray = 
    jdbcManager
        .deleteBatch(employees)
        .execute();

引数はエンティティのリストあるいは配列(可変長引数)で、戻り値は、更新した行数の配列です。 削除するときに、バージョンによる楽観的排他制御をすることができます。 詳しくは、 バージョン定義 を参照してください。

注意点

識別子定義 のないエンティティは、 SQL自動生成によるバッチ削除は出来ません。

バージョンをチェックしないで削除する

バージョンをチェックしないで削除する場合は、 ignoreVersion() を使います。

int count = 
    jdbcManager
        .delete(employee)
        .ignoreVersion()
        .execute();

削除行数をチェックしない

バージョンによる楽観的排他制御を行う場合、 削除できた行数が0だと javax.persistence.OptimisticLockException が発生します。 削除行数を正しく返さないJDBCドライバを使用する場合は、 suppresOptimisticLockException() を呼び出すことで、更新できた行数のチェックを行わなくなります。

int[] countArray = 
    jdbcManager
        .deleteBatch(employees)
        .suppresOptimisticLockException()
        .execute();

バッチ削除のサイズを指定する

バッチ削除のサイズを設定するには batchSize() を使います。

int[] countArray = 
    jdbcManager
        .updateDelete(employees)
        .batchSize(50)
        .execute();

ストアドの呼び出し

ストアドプロシージャの呼び出し

ストアドプロシージャを呼び出す場合は、 call()execute() を組み合わせます。 call() の最初の引数は、 呼び出すストアドプロシージャの名前です。

最初の例は、パラメータのない場合です。

jdbcManager
    .call("myproc")
    .execute();

INのパラメータが1つだけで、そのパラメータが null にならない場合は、 call() の2番目の引数で値を直接指定します。

jdbcManager
    .call("myproc", "hoge")
    .execute();

上記以外の場合は、 call() の2番目の引数にJavaBeansを指定します。 ストアドプロシージャを呼び出すパラメータの順番にJavaBeansのフィールドを定義します。

注意点

S2JDBCは、ソースコード上に記述したフィールドの順番と、 コンパイルされた.classファイル内のフィールドの順番が同じになることを前提としていますが、 これはJavaの仕様では保証されていません. SunのJDKやEclipseではソースコード上と.classファイル内のフィールド順は同じになっていますが、 フィールドの順番が変わってしまう環境ではストアドの呼び出しが失敗します。 フィールドの順番が変わってしまう環境があった場合は Seasar-userメーリングリスト までお知らせください.

  • フィールドにアノテーションが付けられていない場合、 IN パラメータになります。
  • フィールドに @Out アノテーションが付けられている場合、 OUT パラメータになります。
  • フィールドに @InOut アノテーションが付けられている場合、 INOUT パラメータになります。
  • フィールドに @ResultSet アノテーションが付けられている場合、 パラメータ以外で戻される結果セットになります。 ただし、 OracleやPostgreSQLのように、 パラメータ以外で結果セットを返すことが出来ないRDBMSの場合は、 OUT パラメータとして扱われます。
  • フィールドに @Lob が付けられている場合、 そのパラメータはLOBとして扱われます。 @Lob アノテーションは他のアノテーションと組み合わせて使用することが出来ます。
public class MyDto {
    public String arg1; // 第1引数 (IN)

    @Out
    public String arg2; // 第2引数 (OUT)

    @InOut
    public int arg3;    // 第3引数 (INOUT)

    @ResultSet
    public List<String> result; // 結果セット
}
MyDto dto = new MyDto();
dto.arg1 = "hoge";
dto.arg3 = 2;
jdbcManager
    .call("myproc", dto)
    .execute();
System.out.println(dto.arg2);
System.out.println(dto.arg3);
System.out.println(dto.result);

ストアドプロシージャが複数のカラムを持つ結果セットを返す場合は、 対応するフィールドの型を List<結果セットの行に対応するJavaBeansの型> にします。

public class MyDto {
    public int arg1; // 第1引数 (IN)

    @ResultSet
    public List<EmployeeDto> result; // 結果セット
}
MyDto dto = new MyDto();
dto.arg1 = 1;
jdbcManager
    .call("myproc", dto)
    .execute();
System.out.println(dto.result);

オラクルとPostgreSQLの場合は、結果セットをパラメータで受け取る必要があります。 これらのRDBMSでは、 @ResultSet アノテーションが付けられたパラメータは OUT パラメータとして扱われます。

public class MyDto {
    public int arg1; // 第1引数 (IN)

    @ResultSet
    public List<EmployeeDto> result; // 第2引数 (OUT)
}
MyDto dto = new MyDto();
dto.arg1 = 1;
jdbcManager
    .call("myproc", dto)
    .execute();
System.out.println(dto.result);

ストアドファンクションの呼び出し

ストアドファンクションを呼び出す場合は、 call() と、 getSingleResult() または getResultList() を組み合わせます。 call() の1番目の引数でストアドファンクションの戻り値の型を指定します。 2番目の引数でストアドファンクションの名前を指定します。

String result = 
    jdbcManager
        .call(String.class, "myfunc")
        .getSingleResult();

OracleやPostgreSQLのように、 ストアドファンクションの戻り値で結果セットを返すことが出来る場合は getResultList() で結果の List を受け取ります。 call() の1番目の引数で List の要素の型を指定します。

List<String> result = 
    jdbcManager
        .call(String.class, "myfunc")
        .getResultList();

結果セットの行が複数のカラムを持つ場合は List の要素をJavaBeansにします。

List<MyDto> result = 
    jdbcManager
        .call(MyDto.class, "myfunc")
        .getResultList();

INのパラメータが1つだけで、そのパラメータが null にならない場合は、 call() の3番目の引数で値を直接指定します。

String result = 
    jdbcManager
        .call(String.class, "myfunc", "hoge")
        .getSingleResult();

上記以外の場合は、 call() の3番目の引数にJavaBeansを指定します。 ストアドファンクションを呼び出すパラメータの順番にJavaBeansのフィールドを定義します。

注意点

S2JDBCは、ソースコード上に記述したフィールドの順番と、 コンパイルされた.classファイル内のフィールドの順番が同じになることを前提としていますが、 これはJavaの仕様では保証されていません. SunのJDKやEclipseではソースコード上と.classファイル内のフィールド順は同じになっていますが、 フィールドの順番が変わってしまう環境ではストアドの呼び出しが失敗します。 フィールドの順番が変わってしまう環境があった場合は Seasar-userメーリングリスト までお知らせください.

  • フィールドにアノテーションが付けられていない場合、 IN パラメータになります。
  • フィールドに @Out アノテーションが付けられている場合、 OUT パラメータになります。
  • フィールドに @InOut アノテーションが付けられている場合、 INOUT パラメータになります。
  • フィールドに @ResultSet アノテーションが付けられている場合、 パラメータ以外で戻される結果セットになります。 ただし、 OracleやPostgreSQLのように、 パラメータ以外で結果セットを返すことが出来ないRDBMSの場合は、 OUT パラメータとして扱われます。
  • フィールドに @Lob が付けられている場合、 そのパラメータはLOBとして扱われます。 @Lob アノテーションは他のアノテーションと組み合わせて使用することが出来ます。
public class MyDto {
    public String arg1; // 第1引数 (IN)

    @Out
    public String arg2; // 第2引数 (OUT)

    @InOut
    public int arg3;    // 第3引数 (INOUT)

    @ResultSet
    public List<String> result; // 結果セット
}
MyDto dto = new MyDto();
dto.arg1 = "hoge";
dto.arg3 = 2;
String result = 
    jdbcManager
        .call(String.class, "myproc", dto)
        .getSingleResult();
System.out.println(result);
System.out.println(dto.arg1);
System.out.println(dto.arg3);
System.out.println(dto.result);

ストアドファンクションが複数のカラムを持つ結果セットを返す場合は、 対応するフィールドの型を List<結果セットの行に対応するJavaBeansの型> にします。

public class MyDto {
    public int arg1; // 第1引数 (IN)

    @ResultSet
    public List<EmployeeDto> result; // 結果セット
}
MyDto dto = new MyDto();
dto.arg1 = 1;
String result = 
    jdbcManager
        .call(String.class, "myfunc", dto)
        .getSingleResult();
System.out.println(result);
System.out.println(dto.result);

オラクルとPostgreSQLの場合は、戻り値以外の結果セットをパラメータで受け取る必要があります。 これらのRDBMSでは、 @ResultSet アノテーションが付けられたパラメータは OUT パラメータとして扱われます。

public class MyDto {
    public int arg1; // 第1引数 (IN)

    @ResultSet
    public List<EmployeeDto> result; // 第2引数 (OUT)
}
MyDto dto = new MyDto();
dto.arg1 = 1;
String result = 
    jdbcManager
        .call(String.class, "myfunc", dto)
        .getSingleResult();
System.out.println(result);
System.out.println(dto.result);