アプリケーションの設計において、モデル層 (Model)、リポジトリ層 (Repository)、サービス層 (Service) の役割を明確に分けることは、コードの保守性、再利用性、可読性を高めるために重要です。本記事では、それぞれの層の役割と使い分けについて説明します。
モデル層 (Model)
役割
モデル層は、アプリケーションで扱うデータの構造を表現します。具体的には、データベースのテーブルと1対1で対応するエンティティクラスとして定義されることが一般的です。
特徴
データの属性や構造を定義します。
アプリケーションの「状態」を保持します。
データベースのテーブル設計をそのまま反映することが多いです。
例: ユーザーエンティティ
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String email;
private String password;
// Getters and Setters
}
リポジトリ層 (Repository)
役割
リポジトリ層は、データベースへのアクセスや永続化処理を担当します。この層は、モデル層(エンティティ)を操作するメソッドを提供し、データアクセスロジックをアプリケーションの他の部分から隠蔽します。
特徴
データベース操作に特化した責務を持つ。
Spring Data JPA を使用する場合は、JpaRepository や CrudRepository を継承して簡潔に記述可能。
データベースの CRUD (Create, Read, Update, Delete) 操作を抽象化。
例: ユーザーリポジトリ
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
上記のコードでは、findByUsername メソッドがユーザー名でデータを検索する機能を提供します。このメソッドは Spring Data JPA により自動的に実装されます。
サービス層 (Service)
役割
サービス層は、ビジネスロジックを実装する責務を持ちます。リポジトリ層を呼び出してデータを操作し、アプリケーション固有のロジックを組み合わせます。
特徴
アプリケーションの主要な処理を担当。
リポジトリ層を呼び出し、必要なデータ操作を実行。
複数のリポジトリや外部サービスを組み合わせた複雑な処理を実現。
例: ユーザーサービス
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User findUserByUsername(String username) {
return userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
}
public void createUser(User user) {
user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
userRepository.save(user);
}
}
層間の関係
各層は、それぞれ明確な責務を持ち、以下のように連携します:
コントローラ層 (Controller)
ユーザーリクエストを受け取り、サービス層を呼び出します。
サービス層 (Service)
ビジネスロジックを実行し、リポジトリ層を呼び出します。
リポジトリ層 (Repository)
モデル層(エンティティ)を通じてデータベースを操作します。
モデル層 (Model)
データの構造を定義し、リポジトリ層やサービス層で操作されます。
フロー例
ユーザーが新規登録フォームを送信。
コントローラがフォームデータを受け取り、サービス層に渡す。
サービス層が入力データを検証し、必要に応じてリポジトリ層に保存処理を依頼。
リポジトリ層がデータを保存し、結果をサービス層に返す。
サービス層が結果をコントローラに渡し、コントローラがユーザーにレスポンスを返す。
使い分けのポイント
モデル層はデータそのものを表現し、アプリケーションの状態を保持する。
リポジトリ層はデータベースとのやり取りを抽象化し、CRUD 処理を提供する。
サービス層はビジネスロジックを実装し、アプリケーション全体の中核を担う。
この分離により、各層の責務が明確化され、保守性と再利用性が向上します。