<?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="#エンティティ定義">エンティティ定義</a>
					<ul>
						<li><a href="#エンティティリスナー">エンティティリスナー</a></li>
						<li><a href="#ネーミング規約">ネーミング規約</a></li>
						<li><a href="#テーブル">テーブル</a></li>
						<li><a href="#継承">継承</a></li>
					</ul>
				</li>
				<li><a href="#フィールド定義">フィールド定義</a>
					<ul>
						<li><a href="#永続的なフィールド">永続的なフィールド</a>
							<ul>
								<li><a href="#カラム">カラム</a></li>
								<li><a href="#識別子">識別子</a></li>
								<li><a href="#バージョン">バージョン</a></li>
							</ul>
						</li>
						<li><a href="#非永続的なフィールド">非永続的なフィールド</a></li>
						<li><a href="#取得時の状態を管理するフィールド">取得時の状態を管理するフィールド</a></li>
					</ul>
				</li>
				<li><a href="#メソッド定義">メソッド定義</a></li>
				<li><a href="#エンティティの利用方法">エンティティの利用方法</a></li>
			</ul>
		</section>
		<section name="概要">
			<p>
				Entity（エンティティ）は、データベースのテーブルやクエリの結果セットに対応します。
			</p>
			<p>
				このページで説明するアノテーションはすべて<code>org.seasar.doma</code>パッケージに属します。
			</p>
		</section>
		<section name="エンティティ定義">
			<p>
				エンティティクラスは <a href="../apidocs/org/seasar/doma/Entity.html"><code>@Entity</code></a>が注釈されたクラスとして定義します。
				クラスはトップレベルのクラスでなければいけません（他のクラスやインタフェースにネストされていてはいけません）。
				エンティティクラスは 非<code>private</code>なデフォルトコンストラクタ（引数なしのコンストラクタ）を持たなければいけません。
			</p>
<source><![CDATA[@Entity
public class Employee {
    ...
}]]></source>
			<subsection name="エンティティリスナー">
				<p>
					エンティティがデータベースに対し挿入、更新、削除される直前/直後に処理を実行したい場合、
					<code>listener</code> 要素に <code>org.seasar.doma.jdbc.entity.EntityListener</code>
					の実装クラスを指定できます。
				</p>
<source>@Entity(listener = EmployeeEntityListener.class)
public class Employee {
    ...
}</source>
				<p>
					<code>listener</code> 要素に何も指定しない場合、エンティティクラスが他のエンティティクラスを継承しているかどうかで採用する設定が変わります。
				</p>
				<ul>
					<li>継承している場合、親エンティティクラスの設定を引き継ぎます</li>
					<li>継承していない場合、何も行いません（<code>org.seasar.doma.jdbc.entity.NullEntityListener</code> が使用されます）</li>
				</ul>
				<p>
					<code>EntityListener</code>は、<code>preDelete</code>、<code>preInsert</code>、<code>preUpdate</code>、<code>postDelete</code>、<code>postInsert</code>、<code>postUpdate</code>の6つのメソッドをもったインタフェースです。
				</p>
				<dl>
					<dt>preDelete</dt>
					<dd>
						<code>@Delete</code>、または<code>@BatchDelete</code>が注釈されたDaoメソッドでパラメータにエンティティが含まれる場合、削除処理の直前に呼び出されます。
						ただし、使用するエンティティクラスにエンティティリスナーが指定されている必要があります。
					</dd>
					<dt>preInsert</dt>
					<dd>
						<code>@Insert</code>、または<code>@BatchInsert</code>が注釈されたDaoメソッドでパラメータにエンティティが含まれる場合、挿入処理の直前に呼び出されます。
						ただし、使用するエンティティクラスにエンティティリスナーが指定されている必要があります。
					</dd>
					<dt>preUpdate</dt>
					<dd>
						<code>@Update</code>、または<code>@BatchUpdate</code>が注釈されたDaoメソッドでパラメータにエンティティが含まれる場合、更新処理の直前に呼び出されます。
						ただし、使用するエンティティクラスにエンティティリスナーが指定されている必要があります。
					</dd>
					<dt>postDelete</dt>
					<dd>
						<code>@Delete</code>、または<code>@BatchDelete</code>が注釈されたDaoメソッドでパラメータにエンティティが含まれる場合、削除処理の直後に呼び出されます。
						ただし、使用するエンティティクラスにエンティティリスナーが指定されている必要があります。
					</dd>
					<dt>postInsert</dt>
					<dd>
						<code>@Insert</code>、または<code>@BatchInsert</code>が注釈されたDaoメソッドでパラメータにエンティティが含まれる場合、挿入処理の直後に呼び出されます。
						ただし、使用するエンティティクラスにエンティティリスナーが指定されている必要があります。
					</dd>
					<dt>postUpdate</dt>
					<dd>
						<code>@Update</code>、または<code>@BatchUpdate</code>が注釈されたDaoメソッドでパラメータにエンティティが含まれる場合、更新処理の直後に呼び出されます。
						ただし、使用するエンティティクラスにエンティティリスナーが指定されている必要があります。
					</dd>
				</dl>
				<p>
					<code>EntityListener</code>は次のように実装できます。
				</p>
<source><![CDATA[public class EmployeeEntityListener implements EntityListener<Employee> {
    @Override
    public void preDelete(Employee entity, PreDeleteContext<Employee> context) {
        ...
    }
    @Override
    public void preInsert(Employee entity, PreInsertContext<Employee> context) {
        ...
    }
    @Override
    public void preUpdate(Employee entity, PreUpdateContext<Employee> context) {
        ...
    }
    @Override
    public void postDelete(Employee entity, PostDeleteContext<Employee> context) {
        ...
    }
    @Override
    public void postInsert(Employee entity, PostInsertContext<Employee> context) {
        ...
    }
    @Override
    public void postUpdate(Employee entity, PostUpdateContext<Employee> context) {
        ...
    }
}]]></source>
				<p>
					<code>EntityListener</code>の各メソッドの2番目のパラメータは挿入、更新、削除が行われた場合のコンテキスト情報です。
					このコンテキスト情報には、エンティティのメタクラス、Daoのメソッド、Daoの設定が含まれます。
					たとえば、Daoのメソッドに独自のアノテーションをつけておくと、そのアノテーションの有無を見て特定のプロパティを更新するといったことが可能です。
				</p>
				<p>
					<code>EntityListener</code>の実装クラスはpublicなデフォルトコンストラクタ（引数なしのコンストラクタ）を持たねばいけません。
				</p>
			</subsection>
			<subsection name="ネーミング規約">
				<p>
					エンティティに対応するテーブル名やプロパティに対応するカラム名を解決するためのネーミング規約を変更したい場合、
					<code>naming</code> 要素に <code>org.seasar.doma.jdbc.entity.NamingType</code>
					の列挙型を指定できます。
				</p>
<source>@Entity(naming = NamingType.SNAKE_UPPER_CASE)
public class EmployeeInfo {
    ...
}</source>
				<p>
					<code>naming</code> 要素に何も指定しない場合、エンティティクラスが他のエンティティクラスを継承しているかどうかで採用する設定が変わります。
				</p>
				<ul>
					<li>継承している場合、親エンティティクラスの設定を引き継ぎます</li>
					<li>継承していない場合、何も行いません（<code>org.seasar.doma.jdbc.entity.NamingType.NONE</code> が使用されます）</li>
				</ul>
				<p>
					<code>NamingType.SNAKE_UPPER_CASE</code>は、エンティティ名やプロパティ名をスネークケース（アンダースコア区切り）の大文字に変換します。この例の場合、テーブル名は<code>EMPLOYEE_INFO</code>になります。
				</p>
				<p>
					<code>naming</code>要素に何も指定しない場合、デフォルトでは、テーブル名にはエンティティクラスの単純名、カラム名にはプロパティ名が使用されます。
				</p>
				<p>
					ネーミング規約は、<code>@Table</code>や<code>@Colum</code>の<code>name</code>要素が指定されない場合のみ使用されます。
					<code>@Table</code>や<code>@Colum</code>の<code>name</code>要素が指定された場合は、<code>name</code>要素に指定した値が使用され、ネーミング規約は適用されません。
				</p>
				<p>
					<code>NamingType</code>には次の列挙定数があります。
				</p>
				<table border="1" cellpadding="2" cellspacing="0">
					<tr><th>列挙定数</th><th>説明</th></tr>
					<tr><td>NONE</td><td>何も行いません。</td></tr>
					<tr><td>SNAKE_UPPER_CASE</td><td>キャメルケースをスネークケース（アンダースコア区切り）の大文字に変換します。</td></tr>
					<tr><td>SNAKE_LOWER_CASE</td><td>キャメルケースをスネークケース（アンダースコア区切り）の小文字に変換します。</td></tr>
					<tr><td>UPPER_CASE</td><td>大文字に変換します。</td></tr>
					<tr><td>LOWER_CASE</td><td>小文字に変換します。</td></tr>
				</table>
			</subsection>
			<subsection name="テーブル">
				<p>
					エンティティに対応するテーブル情報を指定するには、 <code>@Table</code> を使用します。
				</p>
				<p>
					<code>name</code>要素でテーブル名を指定できます。
				</p>
<source><![CDATA[@Entity
@Table(name = "EMP")
public class Employee {
    ...
}]]></source>
				<p>
					<code>catalog</code>要素や <code>schema</code>要素 でカタログやスキーマを指定できます。
				</p>
<source><![CDATA[@Entity
@Table(catalog = "CATALOG", schema ="SCHEMA", name = "EMP")
public class Employee {
    ...
}]]></source>
				<p>
					<code>@Table</code>を使用しない、もしくは <code>@Table</code>の<code>name</code>要素を使用しない場合、
					テーブル名は、<a href="ネーミング規約">ネーミング規約</a>により解決されます。
				</p>
			</subsection>
			<subsection name="継承">
				<p>
					任意のクラスを継承できます。
				</p>
				<p>
					ただし、親クラスのフィールドが永続フィールドとみなされたりDomaのアノテーションが解釈されたりするのは、親クラスが@Entityで注釈されている場合だけです。
				</p>
			</subsection>
		</section>
		<section name="フィールド定義">
			<subsection name="永続的なフィールド">
				<p>
					永続的なフィールドは、テーブルや結果セットのカラムに対応します。
				</p>
				<p>
					フィールドの型は、<a href="basic.html">基本型</a>もしくは<a href="domain.html">ドメインクラス</a>でなければいけません。
				</p>
<source><![CDATA[@Entity
public class Employee {
    ...
    Integer employeeId;
}]]></source>
			</subsection>
				<h4><a name="カラム"></a>カラム</h4>
				<p>
					プロパティに対応するカラム情報を指定するには、<code>@Column</code>を使用します。
				</p>
				<p>
					<code>name</code>要素でカラム名を指定できます。
				</p>
<source><![CDATA[@Column(name = "ENAME")
String employeeName;]]></source>
				<p>
					<code>insertable</code>要素や <code>updatable</code>要素 で挿入や更新の対象とするかどうかを指定できます。
				</p>
<source><![CDATA[@Column(insertable = false, updatable = false)
String employeeName;]]></source>
				<p>
					<code>@Column</code>を使用しない、もしくは<code>@Column</code>の <code>name</code>要素を使用しない場合、
					カラム名は、<a href="ネーミング規約">ネーミング規約</a>により解決されます。
				</p>
				<h4><a name="識別子"></a>識別子</h4>
				<p>
					識別子(主キー)であることを指定するには、<code>@Id</code>を使います。 
				</p>
<source><![CDATA[@Id
Integer id;]]></source>
				<p>
					複合主キーの場合は <code>@Id</code> を複数指定します。 
				</p>
<source><![CDATA[@Id
Integer id;

@Id
Integer id2;]]></source>
				<p>
					識別子を自動生成する場合は、<code>@GeneratedValue</code>を使用し、
					生成方法を<code>strategy</code>要素に指定します。 
					このアノテーションが注釈されるフィールドの型は数値のプリミティブ型、
					もしくは<code>Number</code>のサブタイプでなければいけません。
				</p>
				<p>
					<code>strategy</code> 要素に指定できる方法は、次の3つです。
				</p>
				<ul>
					<li><code>GenerationType.IDENTITY</code></li>
					<li><code>GenerationType.SEQUENCE</code></li>
					<li><code>GenerationType.TABLE</code></li>
				</ul>
				<h5><code>GenerationType.IDENTITY</code></h5>
				<p>
					データベースのIDENTITY自動生成機能を利用する方法です。RDBMSによってはサポートされていません。
					フィールドに対応するカラムの定義でIDENTITY自動生成を有効にしておく必要があります。
<source><![CDATA[@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;]]></source>
				</p>
				<h5><code>GenerationType.SEQUENCE</code></h5>
				<p>
					データベースのシーケンスを利用する方法です。RDBMSによってはサポートされていません。
				</p>
				<p>
					<code>GenerationType.SEQUENCE</code>を使用するには、
					<code>@SequenceGenerator</code>を併記します。
					<code>@SequenceGenerator</code>では、シーケンスの名前、割り当てサイズ、初期値等を設定できます。
					データベースにあらかじめシーケンスを定義しておく必要がありますが、その定義は<code>@SequenceGenerator</code>の定義とあわせておく必要があります。
				</p>
<source><![CDATA[@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@SequenceGenerator(sequence = "EMPLOYEE_SEQ")
Integer id;]]></source>
				<h5><code>GenerationType.TABLE</code></h5>
				<p>
					生成される識別子をテーブルで管理する方法です。すべてのRDBMSで利用できます。
				</p>
				<p>
					<code>GenerationType.TABLE</code>を使用するには、
					<code>@TableGenerator</code>を併記します。
					<code>@TableGenerator</code>では、テーブル名、割り当てサイズ、初期値等を設定できます。
					データベースにあらかじめテーブルを定義しておく必要がありますが、その定義は<code>@TableGenerator</code>の定義とあわせておく必要があります。
					デフォルトでは、「ID_GENERATOR」という名前のテーブルに、文字列型の「PK」と数値型の「VALUE」という2つのカラムが定義されているものとして動作します（「PK」カラムが主キーです）。
					「PK」カラムにはエンティティクラスごとの一意な名前、「VALUE」カラムには識別子の値が格納されます。
					テーブルには、エンティティクラスごとのレコードをあらかじめ登録しておく必要があります。
				</p>
<source><![CDATA[@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@TableGenerator(pkColumnValue = "EMPLOYEE_ID")
Integer id;]]></source>
				<p>
					<code>@TableGenerator</code>の<code>pkColumnValue</code>要素には、
					識別子を管理するテーブル（デフォルトでは、「ID_GENERATOR」という名前のテーブル）の主キーの値を指定します。
				</p>
				<h4><a name="バージョン"></a>バージョン</h4>
				<p>
					楽観的排他制御用のバージョンは<code>@Version</code>を注釈して示します。
				</p>
				<p>
					フィールドの型は数値のプリミティブ型
					もしくは<code>Number</code>のサブタイプでなければいけません。
				</p>
<source><![CDATA[@Version
Integer version;]]></source>
			<subsection name="非永続的なフィールド">
				<p>
					非永続的なフィールドは、テーブルや結果セットのカラムに対応しません。
				</p>
				<p>
					<code>@Transient</code>を注釈して示します。
					フィールドの型や可視性に制限はありません。
				</p>
<source><![CDATA[@Transient
BigDecimal tempSalary;]]></source>
<source>@Transient
List&lt;String&gt; nameList;</source>
			</subsection>
			<subsection name="取得時の状態を管理するフィールド">
				<p>
					取得時の状態とは、エンティティがDaoから取得されときの全プロパティの値です。
					取得時の状態を保持しておくことで、Daoインタフェースの@Updateが注釈されたメソッドを介して更新処理を実行する際、
					UPDATE文のSET句に変更したフィールドのみを含めるようにすることが可能です。
					取得時の状態を管理するフィールドは、テーブルや結果セットのカラムに対応しません。
				</p>
				<p>
					<code>@OriginalStates</code>を注釈して示します。
					フィールドの型はフィールドが属するエンティティクラスと同じ型でなければいけません。
					<code>@OriginalStates</code>が注釈されたフィールドはアプリケーションで初期化したりアクセスしたりしてはいけません。
				</p>
<source><![CDATA[@OriginalStates
Employee originalStates;]]></source>
				<p>
					<code>@OriginalStates</code>が注釈されたフィールドを持つエンティティの利用法は次のとおりです。
				</p>
<source><![CDATA[@Entity
public class Employee {

   @Id
   Integer id;

   String name;

   Integer age;

   @OriginalStates
   Employee originalStates;

   ...
}]]></source>
<source><![CDATA[EmployeeDao dao = new EmployeeDaoImpl();
Employee employee =dao.selectById(1);
emoloyee.setAge(employee.getAge() + 1);
dao.update(employee);
]]></source>
				<p>
					この例では、UPDATE文のSET句にAGEカラムだけが含まれます。
				</p>
			</subsection>
		</section>
		<section name="メソッド定義">
			<p>
				メソッドの定義に制限はありません。
				フィールドの可視性を<code>protected</code>やパッケージプライベートにしてpublicなメソッド経由でアクセスすることも、
				メソッドを一切使用せず<code>public</code>フィールドに直接アクセスすることもどちらもサポートされています。
			</p>
		</section>
		<section name="エンティティの利用方法">
			<p>
				インスタンス化して使用します。
			</p>
<source><![CDATA[Employee employee = new Employee();
employee.setEmployeeId(1);
employee.setEmployeeName("SMITH");
employee.setSalary(new BigDecimal(1000));]]></source>
			<p>
				エンティティはテーブルに1対1で対応させなければいけないわけではありません。
				たとえば、<code>EMPLOYEE</code>テーブルと<code>DEPARTMENT</code>テーブルを結合した結果もエンティティにマッピングできます。
				そのエンティティクラスを<code>EmpDeptDto</code>とした場合のエンティティクラスの定義とDaoインタフェースの定義は次のとおりです。
			</p>
<source><![CDATA[@Entity
public class EmpDeptDto {
    String employeeName;
    String departmentName;
}]]></source>
<source><![CDATA[@Dao(config = AppConfig.class)
public interface EmployeeDao {
    @Select
    EmpDeptDto selectByDepartmentId(Integer departmentId);
}]]></source>
		</section>
	</body>
</document>