カテゴリ: Spring 更新日: 2026/01/01

JavaのSpring Data JPAでデータを保存・更新・削除する方法!初心者向けガイド

Spring のDB登録/更新/削除(Spring Data JPA)
Spring のDB登録/更新/削除(Spring Data JPA)

先生と生徒の会話形式で理解しよう

生徒

「Spring Data JPAを使ってデータベースにデータを保存する方法を教えてください!」

先生

「もちろんです!Spring Data JPAでは、データの保存や更新、削除が簡単にできます。saveメソッドとdeleteByIdメソッドの使い方を詳しく見ていきましょう。」

生徒

「それは便利ですね!基本的な使い方を知りたいです。」

先生

「では、順を追って具体的に解説しますね。」

1. Spring Data JPAでデータを保存する方法(saveメソッド)

1. Spring Data JPAでデータを保存する方法(saveメソッド)
1. Spring Data JPAでデータを保存する方法(saveメソッド)

データベースに新しいデータを追加するには、saveメソッドを使用します。Spring Data JPAでは、リポジトリインターフェースを使うことでsaveメソッドを簡単に利用できます。


import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Integer> {
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/users/create")
    public String createUser(@RequestParam String username, @RequestParam String email, Model model) {
        User user = new User();
        user.setUsername(username);
        user.setEmail(email);
        userRepository.save(user);
        model.addAttribute("message", "User created successfully");
        return "result";
    }
}

このコードで、/users/createエンドポイントにusernameemailパラメータを渡してリクエストすると、新しいユーザーがデータベースに保存されます。

2. Spring Data JPAでデータを更新する方法(saveメソッド)

2. Spring Data JPAでデータを更新する方法(saveメソッド)
2. Spring Data JPAでデータを更新する方法(saveメソッド)

既存のデータを更新する場合もsaveメソッドを使います。更新したいエンティティのIDを指定し、必要なプロパティを更新してからsaveメソッドで保存します。例えば、ユーザーの情報を更新する場合、次のようにします。


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/users/update")
    public String updateUser(@RequestParam Integer id, @RequestParam String username, @RequestParam String email, Model model) {
        User user = userRepository.findById(id).get();
        user.setUsername(username);
        user.setEmail(email);
        userRepository.save(user);
        model.addAttribute("message", "User updated successfully");
        return "result";
    }
}

このコードでは、/users/updateエンドポイントにid, usernameおよびemailパラメータを渡すことで指定したIDのユーザー情報が更新されます。

3. Spring Data JPAでデータを削除する方法(deleteByIdメソッド)

3. Spring Data JPAでデータを削除する方法(deleteByIdメソッド)
3. Spring Data JPAでデータを削除する方法(deleteByIdメソッド)

データを削除するには、deleteByIdメソッドを使用します。このメソッドは、指定したIDのデータをデータベースから削除します。以下のコード例では、指定したIDのユーザーを削除します。


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/users/delete")
    public String deleteUser(@RequestParam Integer id, Model model) {
        userRepository.deleteById(id);
        model.addAttribute("message", "User deleted successfully");
        return "result";
    }
}

このコードでは、/users/deleteエンドポイントにidパラメータを渡すことで、該当のIDのユーザーが削除されます。

4. saveの挙動と「新規/更新」の判定・まとめて保存(saveAll/saveAndFlush)

4. saveの挙動と「新規/更新」の判定・まとめて保存(saveAll/saveAndFlush)
4. saveの挙動と「新規/更新」の判定・まとめて保存(saveAll/saveAndFlush)

Spring Data JPAのsaveアップサート(insert or update)として動作します。通常、@GeneratedValueでIDを自動採番している場合は、IDが未設定(null)なら新規保存、既存IDが紐づくなら更新になります。大量データはsaveAllでまとめて登録し、即時にDBへ反映したい場面ではsaveAndFlushが便利です(大量処理ではバッチ設定も検討)。


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;
import java.util.Arrays;

@Controller
public class UserBulkController {

    @Autowired
    private UserRepository userRepository;

    // まとめて新規保存(アップサート)
    @GetMapping("/users/bulkCreate")
    public String bulkCreate(Model model) {
        List<User> users = Arrays.asList(
            new User(null, "taro", "taro@example.com"),
            new User(null, "hanako", "hanako@example.com")
        );
        userRepository.saveAll(users);
        model.addAttribute("message", "Users created (bulk)");
        return "result";
    }
}
  

補足:更新は「永続化コンテキスト」に管理されたエンティティなら、@Transactional内でプロパティを書き換えるだけでダーティチェッキングにより自動反映されます(明示save不要)。


import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserWriteService {

    private final UserRepository repo;
    public UserWriteService(UserRepository repo) { this.repo = repo; }

    @Transactional
    public void rename(Integer id, String newName) {
        User u = repo.findById(id).orElseThrow(() -> new IllegalArgumentException("not found"));
        u.setUsername(newName); // トランザクション終了時に自動UPDATE
    }
}
  

5. 削除のベストプラクティス(deleteById/関連のカスケード/論理削除)

5. 削除のベストプラクティス(deleteById/関連のカスケード/論理削除)
5. 削除のベストプラクティス(deleteById/関連のカスケード/論理削除)

deleteByIdは最もシンプルな物理削除です。ただし親子関係(@OneToManyなど)がある場合、外部キー制約でエラーになりがちなので、cascade = CascadeType.REMOVEorphanRemoval = trueを設計段階で検討します。履歴保持が必要なら論理削除(ソフトデリート)のフラグを導入し、検索時は未削除のみを返すクエリメソッドを用意します。


import jakarta.persistence.*;
import java.util.List;

@Entity
public class User {
    @Id @GeneratedValue
    private Integer id;
    private String username;
    private String email;
    private boolean deleted = false; // 論理削除フラグ

    @OneToMany(mappedBy = "user", cascade = CascadeType.REMOVE, orphanRemoval = true)
    private List<Post> posts;

    // getter/setter 省略
}

public interface UserRepository extends JpaRepository<User, Integer> {
    // 論理削除対応の検索
    List<User> findByDeletedFalse();
}
  

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class UserDeleteController {

    @Autowired
    private UserRepository userRepository;

    // 物理削除
    @GetMapping("/users/remove")
    public String remove(@RequestParam Integer id, Model model) {
        userRepository.deleteById(id); // 存在しないIDは例外になる場合あり
        model.addAttribute("message", "User deleted");
        return "result";
    }

    // 論理削除
    @GetMapping("/users/softDelete")
    public String softDelete(@RequestParam Integer id, Model model) {
        User u = userRepository.findById(id).orElse(null);
        if (u == null) {
            model.addAttribute("message", "User not found");
            return "result";
        }
        u.setDeleted(true); // フラグのみ更新
        userRepository.save(u);
        model.addAttribute("message", "User soft-deleted");
        return "result";
    }
}
  

SEO・UXの観点では、「削除後のリダイレクト先」や「確認ダイアログ」も重要です。誤操作防止のため、確認画面→実行の二段階にすると安心です(実運用ではHTTPメソッドもDELETE/POSTに分離)。

6. 保存・更新・削除で起きやすい例外と対策(@Transactional/一意制約/同時更新)

6. 保存・更新・削除で起きやすい例外と対策(@Transactional/一意制約/同時更新)
6. 保存・更新・削除で起きやすい例外と対策(@Transactional/一意制約/同時更新)

CRUD実装では例外処理とトランザクション境界が品質を左右します。代表的には、DataIntegrityViolationException(一意制約やFK制約違反)、EmptyResultDataAccessException(存在しないIDをdeleteById)など。@Transactionalで一連の保存・更新・削除をまとめ、発生時はロールバックしてユーザーに分かりやすいメッセージを返します。


import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class SafeCrudController {

    private final UserWriteService service;

    public SafeCrudController(UserWriteService service) { this.service = service; }

    @GetMapping("/users/safeRename")
    public String safeRename(Integer id, String username, Model model) {
        try {
            service.rename(id, username);
            model.addAttribute("message", "User updated (tx committed)");
        } catch (IllegalArgumentException e) {
            model.addAttribute("message", "User not found");
        } catch (DataIntegrityViolationException e) {
            model.addAttribute("message", "Constraint violation");
        }
        return "result";
    }

    @GetMapping("/users/safeDelete")
    public String safeDelete(Integer id, Model model) {
        try {
            service.delete(id);
            model.addAttribute("message", "User deleted");
        } catch (EmptyResultDataAccessException e) {
            model.addAttribute("message", "User already removed or not found");
        }
        return "result";
    }
}
  

同時更新の競合には楽観的ロック@Version)が有効です。更新時にバージョン不一致を検知して例外を投げ、ユーザーに「他で更新されました」と再入力を促します。これにより「更新の取りこぼし」を防ぎ、タイトル通りの保存・更新・削除を堅牢に実装できます。

まとめ

まとめ
まとめ

この記事では、Spring Data JPAを使ってデータベースにデータを保存、更新、削除する方法について解説しました。saveメソッドとdeleteByIdメソッドを使用することで、初心者でも簡単にCRUD操作を実現できます。Spring Data JPAは、SQLを直接書かなくてもデータ操作ができる点で非常に便利であり、開発効率を大幅に向上させます。

特に、saveメソッドは新規データの追加だけでなく、既存データの更新にも利用できるため、柔軟性に優れています。一方で、deleteByIdメソッドを使えば、特定のIDのデータを簡単に削除することが可能です。これにより、エンティティの管理が非常にシンプルになります。

また、Spring BootのControllerクラスを使用してエンドポイントを作成し、データベース操作をHTTPリクエスト経由で行う方法も学びました。これにより、ウェブアプリケーションのバックエンドでデータ操作を簡単に実装できます。以下に、今回の記事で紹介した主要なコード例をまとめました。


<!-- Userエンティティ -->
import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public class User {
    @Id
    private Integer id;
    private String username;
    private String email;

    // Getter, Setter
}

<!-- UserRepositoryインターフェース -->
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Integer> {
}

<!-- UserControllerクラス -->
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/users/create")
    public String createUser(@RequestParam String username, @RequestParam String email, Model model) {
        User user = new User();
        user.setUsername(username);
        user.setEmail(email);
        userRepository.save(user);
        model.addAttribute("message", "User created successfully");
        return "result";
    }

    @GetMapping("/users/update")
    public String updateUser(@RequestParam Integer id, @RequestParam String username, @RequestParam String email, Model model) {
        User user = userRepository.findById(id).get();
        user.setUsername(username);
        user.setEmail(email);
        userRepository.save(user);
        model.addAttribute("message", "User updated successfully");
        return "result";
    }

    @GetMapping("/users/delete")
    public String deleteUser(@RequestParam Integer id, Model model) {
        userRepository.deleteById(id);
        model.addAttribute("message", "User deleted successfully");
        return "result";
    }
}

これらのコードを参考にすることで、Spring Data JPAを活用したCRUD操作の基本をマスターすることができます。また、HTTPリクエストと連携することで、ウェブアプリケーションに必要なデータ操作機能を簡単に実現可能です。ぜひ、実際のプロジェクトで活用してみてください。

先生と生徒の振り返り会話

生徒

「Spring Data JPAのsaveメソッドって、データの保存だけでなく、更新にも使えるんですね!便利です。」

先生

「その通りです。新規追加も更新も同じメソッドで対応できるのは、Spring Data JPAの強みです。ただし、IDの指定を間違えないように気をつけましょう。」

生徒

「データ削除も簡単ですね。deleteByIdを使うだけなんて驚きました!」

先生

「そうですね。ただし、削除する前に、本当に必要な操作かを確認する仕組みを追加すると、さらに安全になります。」

生徒

「これなら、簡単なCRUDアプリケーションをすぐに作れそうです。次は、もっと複雑な機能に挑戦したいです!」

先生

「いいですね。次回はリレーショナルデータベースの操作や、カスタムクエリについて詳しく学びましょう!」

この記事を読んだ人からの質問

この記事を読んだ人からの質問
この記事を読んだ人からの質問

プログラミング初心者からのよくある疑問/質問を解決します

Spring Data JPAのsaveメソッドは新規作成と更新のどちらに使えますか?

saveメソッドは、新しいデータの作成と既存データの更新の両方に使用できます。新規データの場合はIDを設定せずに保存し、更新の場合は対象データのIDを指定して保存します。

deleteByIdメソッドを使うとき、対象のデータが存在しない場合はどうなりますか?

deleteByIdメソッドを実行すると、対象データが存在しない場合に例外がスローされます。実行前に存在を確認する方法を追加すると安全です。

findByIdメソッドでデータが見つからない場合はどう処理しますか?

findByIdメソッドはOptionalを返すため、データが見つからない場合はisPresentでチェックしたり、orElseThrowを使ってカスタム例外をスローできます。

Spring Bootプロジェクトでデータベース接続情報を設定するにはどうすればいいですか?

データベース接続情報はapplication.propertiesまたはapplication.ymlに記載します。例えば、MySQLを使う場合はURL、ユーザー名、パスワードを設定します。

データベースの初期データを登録するにはどうすればいいですか?

初期データはsrc/main/resourcesディレクトリにdata.sqlファイルを配置することで、自動的に登録されます。テーブル作成はschema.sqlファイルを使用します。

saveメソッドで更新を行う際、他のフィールドの値を変更せずに維持するにはどうすればいいですか?

findByIdでエンティティを取得し、必要なフィールドのみを変更してからsaveメソッドを呼び出します。これにより、他のフィールドの値は維持されます。

Spring Data JPAで複数のエンティティを一括削除する方法はありますか?

リポジトリのdeleteAllメソッドを使用すると、全データを一括削除できます。また、deleteAllInBatchを使えば、バッチ処理で効率的に削除可能です。

saveメソッドを使った操作で同時実行制御を行うにはどうすればいいですか?

@Transactionalアノテーションを使用してトランザクション管理を行うことで、同時実行制御を適用できます。また、必要に応じてロック機構を追加することも可能です。

Spring Data JPAでのエラーハンドリングのベストプラクティスは何ですか?

例外をキャッチして適切なレスポンスを返すために、@ControllerAdviceを使用してカスタム例外ハンドラを作成するのがおすすめです。

Spring Data JPAでカスタムクエリを作成するにはどうすればいいですか?

@Queryアノテーションをリポジトリメソッドに追加することで、カスタムSQLを記述できます。JPQLやネイティブクエリもサポートされています。
カテゴリの一覧へ
新着記事
JavaのHttpServletResponseWrapperを完全解説!初心者でも理解できるレスポンス処理のしくみ
JavaのScannerクラスの使い方を徹底解説!初心者でも簡単に学べる入力処理
JavaのArrayListクラスとaddメソッドを完全解説!初心者でもわかるリスト操作
Javaの@Idアノテーションを徹底解説!初心者でもわかるデータベースとの連携方法
人気記事
No.1
Java&Spring記事人気No1
Spring BootとJavaの互換性一覧!3.5/3.4/3.3はJava 21・17に対応してる?
No.2
Java&Spring記事人気No2
Javaのラムダ式で配列を扱う!Arrays.streamの基本と注意点を初心者向けに解説
No.3
Java&Spring記事人気No3
JavaのRuntimeExceptionを完全解説!初心者でもわかるjava.langパッケージの基礎
No.4
Java&Spring記事人気No4
JavaのBigDecimalクラスcompareToメソッド完全ガイド!初心者でもわかる大小比較の基本
No.5
Java&Spring記事人気No5
JavaのIntegerクラスの使い方を完全ガイド!初心者でもわかる整数操作
No.6
Java&Spring記事人気No6
Springの@Serviceアノテーションの使い方を徹底解説!初心者でもわかるSpring フレームワーク入門
No.7
Java&Spring記事人気No7
Javaの@SuppressWarningsアノテーションの使い方を完全ガイド!初心者でもわかる警告の抑制方法
No.8
Java&Spring記事人気No8
JSPとは何か?初心者向けにできること・仕組み・特徴をやさしく解説