Javaにおけるデータマッパーパターン:データストレージとビジネスロジックの分離
別名
- オブジェクト関係マッピング(ORM)
データマッパーパターンの目的
データマッパーパターンは、データベースとビジネスロジックの間に抽象化レイヤーを作成し、それらを独立して進化させることを目的としています。データベースオブジェクトからメモリ内のデータ構造に、またその逆にデータをマッピングすることで、アプリケーションのコアロジックと基盤となるデータベース構造間の直接的な依存関係を最小限に抑えます。この分離は、Javaプログラミングにおける保守性と柔軟性を促進するために不可欠です。
現実世界の例を用いたデータマッパーパターンの詳細な説明
現実世界の例
書籍が、タイトル、著者、出版年、ジャンルなど、複雑な関係とさまざまな属性を持つデータベースに保存されているライブラリシステムを考えてみましょう。このシナリオでは、データマッパーパターンを使用して、書籍のデータベースレコードをアプリケーション内のメモリ内オブジェクトにマッピングできます。データマッパーは、データベース内の書籍オブジェクトの取得、保存、更新を処理し、アプリケーションのビジネスロジックが基盤となるデータベース構造を気にすることなく書籍オブジェクトを直接操作できるようにします。この分離により、ビジネスロジックに影響を与えることなくデータベーススキーマを変更することが容易になり、その逆も同様です。
簡単な言葉で
オブジェクトとデータベース間でデータを移動し、互いに独立した状態を保つマッパーの層。
Wikipediaによると
データマッパーは、永続データストア(多くの場合、リレーショナルデータベース)とメモリ内データ表現(ドメイン層)の間で双方向のデータ転送を実行するデータアクセス層です。このパターンの目標は、メモリ内表現と永続データストアを互いに、そしてデータマッパー自体から独立させることです。これは、永続データストアにうまくマッピングされないドメイン層のデータに厳密なビジネスプロセスをモデル化して適用する必要がある場合に役立ちます。
Javaにおけるデータマッパーパターンのプログラム例
データマッパーは、メモリ内オブジェクトをデータベースから分離するデザインパターンです。その役割は、2つの間でデータを転送し、互いに分離することです。このパターンは、単一責任原則と関心の分離を促進します。
データマッパーモジュールでは、 `Student` クラスと `StudentDataMapper` インターフェースを使用してパターンが示されています。
`Student` クラスは、学生を表すシンプルなPOJO(Plain Old Java Object)です。 studentId、名前、学年などのプロパティがあります。
public class Student {
private int studentId;
private String name;
private char grade;
// ...
}
`StudentDataMapper` インターフェースは、 `Student` オブジェクトに対して実行できる操作を定義します。これらの操作には、 `insert`、 `update`、 `delete`、 `find` が含まれます。
public interface StudentDataMapper {
void insert(final Student student);
void update(final Student student);
void delete(final Student student);
Optional<Student> find(final int studentId);
// ...
}
`StudentDataMapperImpl` クラスは、 `StudentDataMapper` インターフェースを実装します。データベースと対話するための実際のロジックが含まれています。
public class StudentDataMapperImpl implements StudentDataMapper {
// ...
@Override
public void insert(final Student student) {
// Insert student into the database
}
@Override
public void update(final Student student) {
// Update student in the database
}
@Override
public void delete(final Student student) {
// Delete student from the database
}
@Override
public Optional<Student> find(final int studentId) {
// Find student in the database
}
// ...
}
`App` クラスには、 `StudentDataMapper` の使用方法を示す `main` メソッドが含まれています。 `Student` オブジェクトを作成し、データベースに挿入し、見つけ、更新し、最後に削除します。
public class App {
public static void main(final String... args) {
final var mapper = new StudentDataMapperImpl();
var student = new Student(1, "Adam", 'A');
mapper.insert(student);
final var studentToBeFound = mapper.find(student.getStudentId());
student = new Student(student.getStudentId(), "AdamUpdated", 'A');
mapper.update(student);
mapper.delete(student);
}
}
プログラム出力
13:54:29.234 [main] DEBUG com.iluwatar.datamapper.App -- App.main(), student : Student(studentId=1, name=Adam, grade=A), is inserted
13:54:29.237 [main] DEBUG com.iluwatar.datamapper.App -- App.main(), student : Optional[Student(studentId=1, name=Adam, grade=A)], is searched
13:54:29.237 [main] DEBUG com.iluwatar.datamapper.App -- App.main(), student : Student(studentId=1, name=AdamUpdated, grade=A), is updated
13:54:29.238 [main] DEBUG com.iluwatar.datamapper.App -- App.main(), student : Student(studentId=1, name=AdamUpdated, grade=A), is going to be deleted
Javaでデータマッパーパターンを使用する場合
以下のいずれかの状況でデータマッパーを使用します
- 単一責任原則と関心の分離を促進するために、メモリ内オブジェクトをデータベースエンティティから分離する必要がある場合。
- オブジェクト指向モデルとリレーショナルデータベース間のギャップを埋めるためにORMツールを必要とするアプリケーションの場合。
- 直接データ操作とオブジェクト作成が煩雑でエラーが発生しやすいコードにつながる複雑なデータベーススキーマを扱う場合。
データマッパーパターン Javaチュートリアル
- Spring Boot RowMapper (ZetCode)
- Spring BeanPropertyRowMapper チュートリアル (ZetCode)
- Javaにおけるデータ転送オブジェクトパターン - 実装とマッピング (StackAbuse)
Javaにおけるデータマッパーパターンの現実世界のアプリケーション
- JavaのHibernateなどのORMフレームワーク。
- ビジネスロジックとデータベース管理が分離されているエンタープライズアプリケーションのデータアクセス層。
- コードを特定のデータベース実装に結び付けることなく、データベースとの対話を必要とするアプリケーション。
データマッパーパターンの利点とトレードオフ
利点
- 永続化ロジックをビジネスロジックから分離することにより、単一責任原則を促進します。
- データインタラクションロジックを一元化することにより、保守性と可読性を向上させます。
- ビジネスロジックに最小限の変更を加えるだけで、データベーススキーマの変更に適応するアプリケーションの能力を向上させます。
トレードオフ
- 追加の抽象化レイヤーによって複雑さが増します。
- 抽象化レイヤーが原因で、特に大規模アプリケーションや複雑なクエリでパフォーマンスのオーバーヘッドが発生する可能性があります。
- 開発者は、使用されているデータベースとORMフレームワークに加えて、抽象化レイヤーを学習して理解する必要があります。
関連するJavaデザインパターン
- アクティブレコード:データマッパーの関心の分離とは対照的に、データアクセスロジックとビジネスロジックをドメインエンティティ自体に組み合わせます。
- オブジェクトリレーショナルマッピング(ORM):オブジェクト指向プログラミング言語データをリレーショナルデータベースにマッピングする手法。
- リポジトリ:データ層の抽象化を提供し、メモリ内のドメインオブジェクトのコレクションとして機能します。
- 作業単位:トランザクションを管理し、ビジネストランザクションの影響を受けるオブジェクトを追跡して、変更の整合性とトランザクション性を確保します。