ドメインクラス
ドメインクラスはデータベースのカラムを表し、カラムの値を Java オブジェクトとして処理できるようにします。 Doma フレームワークでは、ドメイン はデータ型に含まれる可能性のあるすべての値を意味します。つまり、ドメインクラスは、カラムにマップできるユーザー定義のクラスです。ドメインクラスの使用はオプションです。
すべてのドメインクラスは、内部ドメインクラスまたは外部ドメインクラスのいずれかです。
内部ドメインクラス
内部ドメインクラスには @Domain
アノテーションを付ける必要があります。 @Domain
の valueType
要素は、カラムのデータ型に対応します。 valueType
要素には任意のタイプの 基本クラス を指定します。
コンストラクタを使用したインスタンス化
@Domain
の factoryMethod
要素のデフォルト値は new
です。値 new
は、アノテーションが付けられたクラスのオブジェクトがコンストラクタを使用して作成されることを意味します。
@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() {
...
}
}
注釈
Java 14 以降のバージョンでは、records に @Domain
アノテーションを付けることができます。
@Domain(valueType = String.class, accessorMethod = "value")
public record PhoneNumber(String value) {
public String getAreaCode() {
...
}
}
警告
レコードに @Domain
アノテーションを付けるのは少し冗長です。 valueType
などのいくつかのプロパティを明示的に @Domain
に指定する必要があるためです。 @Domain
の代わりに、レコードに @DataType
アノテーションを付けることができます。
@DataType
public record PhoneNumber(String value) {
public String getAreaCode() {
...
}
}
静的ファクトリメソッドによるインスタンス化
アノテーションが付与されたクラスのオブジェクトを静的ファクトリメソッドで作成するには、 @Domain
の factoryMethod
要素にメソッド名を指定します。
メソッドは静的で非プライベートである必要があります。
@Domain(valueType = String.class, factoryMethod = "of")
public class PhoneNumber {
private final String value;
private PhoneNumber(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public String getAreaCode() {
...
}
public static PhoneNumber of(String value) {
return new PhoneNumber(value);
}
}
静的ファクトリメソッドを使用すると、@Domain
アノテーションを列挙型に適用できます。
@Domain(valueType = String.class, factoryMethod = "of")
public enum JobType {
SALESMAN("10"),
MANAGER("20"),
ANALYST("30"),
PRESIDENT("40"),
CLERK("50");
private final String value;
private JobType(String value) {
this.value = value;
}
public static JobType of(String value) {
for (JobType jobType : JobType.values()) {
if (jobType.value.equals(value)) {
return jobType;
}
}
throw new IllegalArgumentException(value);
}
public String getValue() {
return value;
}
}
内部ドメインクラスにおける型パラメータの使用
内部ドメインクラスには任意の数の型パラメータを宣言できます。
@Domain(valueType = int.class)
public class Identity<T> {
private final int value;
public Identity(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
静的ファクトリメソッドを使用してアノテーション付きクラスのオブジェクトを作成する場合、メソッド宣言にはクラス宣言と同じ型パラメータが必要です。
@Domain(valueType = int.class, factoryMethod = "of")
public class Identity<T> {
private final int value;
private Identity(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static <T> Identity<T> of(int value) {
return new Identity<T>(value);
}
}
外部ドメインクラス
この機能を使用すると、クラスに @Domain
アノテーションを付けられない場合でも、任意のクラスをドメインクラスとして定義できます。
外部ドメイン クラスを定義するには、次のようにします。
org.seasar.Doma.jdbc.domain.DomainConverter
を実装するクラスを作成し、クラスに@ExternalDomain
アノテーションを付ける@DomainConverters
アノテーションを付けたクラスを作成する@DomainConverters
のvalue
要素に@ExternalDomain
アノテーションを付けたクラスを指定するアノテーションプロセッシング のオプションに
@DomainConverters
アノテーションを付けたクラスの完全修飾名を指定する
たとえば、ソースコードを変更でない PhoneNumber
クラスがあるとします。
public class PhoneNumber {
private final String value;
public PhoneNumber(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public String getAreaCode() {
...
}
}
まず、PhoneNumber
クラスを外部ドメインクラスとして定義するために、次のクラスを作成します。
@ExternalDomain
public class PhoneNumberConverter implements DomainConverter<PhoneNumber, String> {
public String fromDomainToValue(PhoneNumber domain) {
return domain.getValue();
}
public PhoneNumber fromValueToDomain(String value) {
if (value == null) {
return null;
}
return new PhoneNumber(value);
}
}
次に、次のクラスを作成し、上記のクラスを @DomainConverters
の value
要素に指定します。
@DomainConverters({ PhoneNumberConverter.class })
public class DomainConvertersProvider {
}
最後に、アノテーションプロセッシング のオプションに上記クラスの完全修飾名を指定します。 Gradle を使用する場合は、ビルド スクリプトで次のようにオプションを指定します。
compileJava {
options {
compilerArgs = ['-Adoma.domain.converters=example.DomainConvertersProvider']
}
}
外部ドメインクラスにおける型パラメータの使用
外部ドメインクラスには任意の数の型パラメータを宣言できます。
public class Identity<T> {
private final int value;
public Identity(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
DomainConverter
実装クラスで、外部ドメインクラスへの型引数としてワイルドカード ?
を指定します。
@ExternalDomain
public class IdentityConverter implements DomainConverter<Identity<?>, String> {
public String fromDomainToValue(Identity<?> domain) {
return domain.getValue();
}
@SuppressWarnings("rawtypes")
public Identity<?> fromValueToDomain(String value) {
if (value == null) {
return null;
}
return new Identity(value);
}
}
例
上記のドメインクラスは次のように使用されます。
@Entity
public class Employee {
@Id
Identity<Employee> employeeId;
String employeeName;
PhoneNumber phoneNumber;
JobType jobType;
@Version
Integer versionNo();
...
}
@Dao
public interface EmployeeDao {
@Select
Employee selectById(Identity<Employee> employeeId);
@Select
Employee selectByPhoneNumber(PhoneNumber phoneNumber);
@Select
List<PhoneNumber> selectAllPhoneNumber();
@Select
Employee selectByJobType(JobType jobType);
@Select
List<JobType> selectAllJobTypes();
}