JavaのSpring Data JPAでデータを保存・更新・削除する方法!初心者向けガイド
生徒
「Spring Data JPAを使ってデータベースにデータを保存する方法を教えてください!」
先生
「もちろんです!Spring Data JPAでは、データの保存や更新、削除が簡単にできます。saveメソッドとdeleteByIdメソッドの使い方を詳しく見ていきましょう。」
生徒
「それは便利ですね!基本的な使い方を知りたいです。」
先生
「では、順を追って具体的に解説しますね。」
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エンドポイントにusernameとemailパラメータを渡してリクエストすると、新しいユーザーがデータベースに保存されます。
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メソッド)
データを削除するには、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)
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/関連のカスケード/論理削除)
deleteByIdは最もシンプルな物理削除です。ただし親子関係(@OneToManyなど)がある場合、外部キー制約でエラーになりがちなので、cascade = CascadeType.REMOVEやorphanRemoval = 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/一意制約/同時更新)
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アプリケーションをすぐに作れそうです。次は、もっと複雑な機能に挑戦したいです!」
先生
「いいですね。次回はリレーショナルデータベースの操作や、カスタムクエリについて詳しく学びましょう!」