【Spring Boot】Service層の役割をやさしく解説

Java入門・実践
スポンサーリンク
スポンサーリンク

はじめに

Spring Boot のコードを書いていると、
Controller / Service / Repository の
3 つの層をよく目にします。

その中でも Service 層 は、
「なんとなく真ん中にあるけど、何をする層なの?」
と迷いやすい場所です。

この記事では、Service 層の役割を
やさしく・実務で役立つ形 で整理していきます。

まずは全体像から見ていきましょう。

Service 層とは

一言でいうと、

「アプリのビジネスロジックをまとめる“司令塔”の層」

です。

  • Controller → リクエストの受付
  • Service → 業務処理の中心
  • Repository → DB とのやり取り

この中で Service は、 アプリの“頭脳” のような役割を持っています。

Service 層の役割を具体的に整理する

ビジネスロジックを実装する

アプリが提供する“本来の処理”を書く場所です。

例:

  • ユーザー登録のルール
  • 在庫チェック
  • ポイント計算
  • 料金の算出
Java
@Service
public class OrderService {

    public int calculatePrice(int base, int discount) {
        return base - discount;
    }
}

Controller に書くと肥大化するため、
Service に集約します。

複数の Repository を組み合わせる

Service は複数のデータソースを扱えます。

例:

  • ユーザー情報を取得
  • 注文情報を取得
  • それらを組み合わせてレスポンスを作る
Java
@Service
public class UserDetailService {

    private final UserRepository userRepository;
    private final OrderRepository orderRepository;

    public UserDetailService(UserRepository userRepository, OrderRepository orderRepository) {
        this.userRepository = userRepository;
        this.orderRepository = orderRepository;
    }

    public UserDetailResponse getDetail(Long id) {
        User user = userRepository.findById(id).orElseThrow();
        List<Order> orders = orderRepository.findByUserId(id);
        return new UserDetailResponse(user, orders);
    }
}

Controller ではなく Service が担うべき処理です。

トランザクション管理を行う

データの整合性を保つために
@Transactional を付けるのは Service 層が基本です。

Java
@Transactional
public void createOrder(OrderRequest req) {
    // 複数の DB 操作をまとめて実行
}

Controller に付けるのはアンチパターンです。

業務的なバリデーションを行う

入力チェック(形式)は Controller / DTO で行いますが、
業務ルールのチェック は Service の役割です。

例:

  • 在庫が 0 の商品は購入できない
  • 同じメールアドレスは登録できない
  • 退会済みユーザーはログインできない
Java
if (user.isDeleted()) {
    throw new BusinessException("退会済みユーザーです");
}

例外を投げて ControllerAdvice に渡す

Service 層で例外を投げ、
ControllerAdvice でレスポンスを整えるのが実務的です。

Java
throw new UserNotFoundException("ユーザーが見つかりません");

Service 層に書かないこと

HTTP の処理

  • @RequestBody
  • @RequestParam
  • @PathVariable

これらは Controller の役割です。

DB の直接操作

SQL や ORM の操作は Repository に任せます。

画面やレスポンスの整形

Service は“処理”に集中し、
レスポンスの形は Controller が決めます。

実務でよくあるアンチパターン

Controller にロジックを書いてしまう

→ 画面が増えると地獄になります。

Service がただの中継役になる

Java
return repository.findById(id);

→ これでは Service の意味がありません。

Repository に業務ロジックを書く

→ DB に依存した設計になり、変更に弱くなります。

Service 層をもっと活かすポイント

DTO を使って Controller と役割を分離

Java
public UserResponse findUser(Long id)

例外クラスでエラーを整理

Java
throw new BusinessException("ルール違反です");

テストしやすい構造にする

Service は単体テストがしやすい層です。

まとめ

Service 層は、
「アプリのビジネスロジックを担う中心の層」
です。

  • 業務処理をまとめる
  • 複数の Repository を組み合わせる
  • トランザクション管理
  • 業務的なバリデーション
  • 例外を投げて Controller に渡す

難しく聞こえますが、
「受付(Controller)とデータ係(Repository)の間で、頭脳として働く層」
と理解できれば十分です。


decopon
decopon

Service 層の役割を理解すると、
Controller と Repository の境界が一気にクリアになります。
ロジックが整理されるだけで、設計もテストもぐっと楽になります。
あなたの開発が、今日より少しだけ楽になりますように。

moco
moco

司令塔ってかっこいいね…みんなをまとめてくれる存在、すてき…

コメント

タイトルとURLをコピーしました