導入
@Entity でテーブルとクラスが結びついたら、次は「保存する」「探す」「削除する」といった操作をどう書くかです。SQLを自分で書かずに、これらをどう実現するのでしょうか。
説明
Spring Data JPAでは、インターフェースを1つ定義するだけでCRUD(Create/Read/Update/Delete)操作が手に入ります。
public interface UserRepository extends JpaRepository<User, Long> {
// 中身は空でよい! Long は主キーの型
}
驚くべきことに、UserRepository には実装クラスを一切書いていません。Spring Data JPAが起動時にこのインターフェースを見つけ、実装クラスを自動生成(プロキシとして動的に作成) し、Beanとして登録します。
graph TD Iface["interface UserRepository<br/>extends JpaRepository<User, Long>"] -->|起動時に自動生成| Proxy["実装クラス(プロキシ)<br/>save/findById/findAll等を実装済み"] Proxy -->|Beanとして登録| Ctx["ApplicationContext"]
JpaRepository を継承した時点で、次のようなメソッドがすでに使えます。
@Service
class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User create(User user) {
return userRepository.save(user); // INSERT または UPDATE
}
public Optional<User> findOne(Long id) {
return userRepository.findById(id); // SELECT ... WHERE id = ?
}
public List<User> findAll() {
return userRepository.findAll(); // SELECT * FROM users
}
public void remove(Long id) {
userRepository.deleteById(id); // DELETE ... WHERE id = ?
}
}
| メソッド | やること |
|---|---|
save(entity) | 新規保存、または既存データの更新 |
findById(id) | 主キーで1件取得(Optional で返る=見つからない可能性がある) |
findAll() | 全件取得 |
deleteById(id) | 主キーで1件削除 |
findById の戻り値が User ではなく Optional<User> になっている点に注目してください。「見つからないかもしれない」ということが型で表現されており、呼び出し側は null チェックの代わりに Optional の機能(orElseThrow など)を使って安全に扱えます。
やってみよう
「メールアドレスで既存ユーザーを検索して見つからなければ登録する」という処理を、UserRepository の findById 以外のメソッドが必要になりそうだと気づけましたか。次のレッスンでその方法を扱います。