Spring Data JPA入門!findAll()やfindBy**()の使い方などデータベース操作の基礎を学ぶ
生徒
「Spring Data JPAって何ですか?」
先生
「Spring Data JPAは、JavaのSpring Frameworkでデータベースとやり取りを簡単にするためのライブラリです。データの取得や保存を簡単にしてくれますよ。」
生徒
「それは便利そうですね!設定方法とか、使い方の基本も知りたいです。」
先生
「では、基本的な設定から実際のコード例まで順を追って説明していきますね!」
1. Spring Data JPAとは?
Spring Data JPAは、面倒なSQLを書かなくても、データベースとやり取りできる便利な仕組みです。 通常はINSERTやSELECTといったSQLを覚える必要がありますが、Spring Data JPAでは 「保存したい」「一覧を取得したい」といった操作が、シンプルなメソッド呼び出しだけで実現できます。
特に初心者にうれしいポイントは、JpaRepositoryというインターフェースを継承するだけで
基本的なCRUD(作成・読み取り・更新・削除)が自動で使えることです。
例えば、以下のようにリポジトリを作成するだけで、データを保存したり全件取得したりできるようになります。
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Integer> {
// 何も書かなくても save() findAll() deleteById() などが使える
}
SQLを書く代わりに、リポジトリ経由でメソッドを呼び出すだけなので、 「データベースって難しそう」と感じている人でも始めやすいのが特徴です。 プログラミング初心者でも、まずはプロジェクトを作り、上記のようなリポジトリを用意するだけで データベース操作を体験できます。 実際の動作はサービスクラスなどから呼び出すだけなので、自然な形で学習できます。
2. データベース接続情報の設定(application.properties)
Spring Bootプロジェクトでデータベースを使うには、src/main/resources/application.propertiesにデータベースの接続設定を書きます。例えば、MySQLデータベースに接続する場合は以下のように記述します。
spring.datasource.url=jdbc:mysql://localhost:3306/your_database
spring.datasource.username=root
spring.datasource.password=your_password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
これで、データベースとの接続が確立されます。spring.datasource.urlには、データベースのURLを指定し、usernameとpasswordにはそれぞれのデータベース情報を入力します。spring.jpa.show-sql=trueは、実行されるSQLをログに表示する設定です。
将来を見据えて、+αのスキルを身につけたい方へ
JavaやLinuxを学んでいても、「このままで市場価値は上がるのか」 「キャリアの選択肢を広げたい」と感じる方は少なくありません。
AIを学ぶならアイデミープレミアム3. schema.sqlとdata.sqlでDBデータ準備
データベースのテーブルを自動生成したり、初期データを投入したい場合は、schema.sqlとdata.sqlファイルを使用します。これらのファイルをsrc/main/resourcesに置くことで、Spring Bootがアプリケーション起動時に自動で読み込んでくれます。
-- schema.sql
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100)
);
-- data.sql
INSERT INTO users (username, email) VALUES ('john_doe', 'john@example.com');
INSERT INTO users (username, email) VALUES ('jane_doe', 'jane@example.com');
これで、usersというテーブルが作成され、指定したデータが初期投入されます。Spring Data JPAを使う準備が整いました。
4. findAllメソッドでデータを取得する
Spring Data JPAのリポジトリインターフェースを利用することで、findAllメソッドを使用してテーブル内の全データを取得することができます。リポジトリは、JpaRepositoryインターフェースを拡張して作成します。
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.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> getAllUsers() {
return userRepository.findAll();
}
}
ここでは、getAllUsersメソッドでfindAllを呼び出し、すべてのUserエンティティを取得しています。findAllを使うことで、データベース内のすべてのデータを簡単に取得できます。
5. findBy***で条件付きデータ取得
特定の条件に基づいてデータを取得したい場合、Spring Data JPAのメソッド名の規約に基づいて、findByを使うことができます。例えば、usernameに基づいてデータを取得するには、以下のようにリポジトリメソッドを定義します。
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Integer> {
User findByUsername(String username);
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User getUserByUsername(String username) {
return userRepository.findByUsername(username);
}
}
このコードでは、usernameが一致するユーザーを取得するfindByUsernameメソッドを定義しています。このようにfindByに続けてカラム名を付けるだけで、条件付きのデータ取得が簡単に実現できます。
6. ページングとソート:findAll(Pageable)/Sortで効率よく取り出す
大量データを一括取得するとメモリを圧迫します。PageableとSortを使えば、ページ単位で取り出し順序も指定できます。findAll(Pageable)はすべてのエンティティを対象に、findBy***と組み合わせれば条件付きのページングができます。
// Repository: 条件付きページング検索を追加
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Integer> {
Page<User> findByUsernameContaining(String keyword, Pageable pageable);
}
// Service: ページング+ソートの例
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) { this.userRepository = userRepository; }
// 全件ページング
public Page<User> getUsers(int page, int size) {
return userRepository.findAll(PageRequest.of(page, size, Sort.by("id").descending()));
}
// キーワード検索+ページング
public Page<User> searchUsers(String keyword, int page, int size) {
var pageable = PageRequest.of(page, size, Sort.by("username").ascending());
return userRepository.findByUsernameContaining(keyword, pageable);
}
}
Pageは総件数・総ページ数・現在ページなどのメタ情報も持つため、一覧画面のページネーション実装が簡単になります。
7. 派生クエリの表現力:And/Or/Containing/Between/In/OrderBy など
findByに続けてプロパティ名とキーワードを連結するだけで多彩な条件を表現できます。代表例を覚えておくと、SQLを書かずに実用的な検索ができます。
public interface UserRepository extends JpaRepository<User, Integer> {
// 複合条件
List<User> findByUsernameAndEmail(String username, String email);
List<User> findByUsernameOrEmail(String username, String email);
// 部分一致・大文字小文字無視
List<User> findByUsernameContainingIgnoreCase(String keyword);
// 範囲・集合・NULL判定
List<User> findByIdBetween(Integer start, Integer end);
List<User> findByIdIn(Collection<Integer> ids);
List<User> findByEmailIsNull();
// 件数制限・並び替え
List<User> findTop5ByOrderByIdDesc();
List<User> findByUsernameContainingOrderByIdAsc(String keyword);
}
基本は「プロパティ+演算子」。存在しないプロパティ名やスペルミスは起動時に検出されるため、早期にバグに気づけます。
8. 保存・更新・削除の基本:save()/saveAll()/deleteById() と Optional の扱い
永続化(保存・更新)はsave、一括はsaveAll、削除はdeleteById等を使います。読み取り時のfindByIdはOptionalを返すため、存在しない場合のハンドリングを忘れないようにします。更新系はトランザクション境界(@Transactional)内で行うのが基本です。
import jakarta.persistence.EntityNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserWriteService {
private final UserRepository userRepository;
public UserWriteService(UserRepository userRepository) { this.userRepository = userRepository; }
@Transactional
public User createUser(String username, String email) {
User u = new User();
u.setUsername(username);
u.setEmail(email);
return userRepository.save(u); // 新規保存
}
@Transactional
public User updateEmail(int id, String newEmail) {
User u = userRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("User not found: " + id));
u.setEmail(newEmail);
return userRepository.save(u); // 変更検知でもOK
}
@Transactional
public void deleteUser(int id) {
userRepository.deleteById(id);
}
}
参照だけ欲しい場合は遅延ロードのgetReferenceById(id)も利用できます(存在チェックは実体アクセス時)。
9. 複雑な検索は @Query(JPQL/Native)で柔軟に記述する
派生クエリで表現しづらい条件は@Queryを使います。JPQLはエンティティ名・プロパティ名で書く抽象化されたクエリ、nativeQuery=trueで生SQLも実行できます。ページングと併用も可能です。
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface UserRepository extends JpaRepository<User, Integer> {
// JPQL:ユーザー名またはメールの部分一致(ページング対応)
@Query("SELECT u FROM User u " +
"WHERE LOWER(u.username) LIKE LOWER(CONCAT('%', :kw, '%')) " +
" OR LOWER(u.email) LIKE LOWER(CONCAT('%', :kw, '%'))")
Page<User> searchByKeyword(@Param("kw") String keyword, Pageable pageable);
// ネイティブSQL:メールドメインで検索
@Query(value = "SELECT * FROM users WHERE email LIKE CONCAT('%', :domain)",
nativeQuery = true)
List<User> findByEmailDomain(@Param("domain") String domain);
}
更新系のカスタムSQLを使う場合は@Modifyingと@Transactionalを併用します(書き込みであることを明示)。
まとめ
この記事では、Spring Data JPAを使用したデータベース操作について詳しく解説しました。初心者の方でもデータベース操作を簡単に行えるようになる基本的な内容から、実際のコーディング例までを網羅しています。特に、Spring Data JPAのリポジトリを利用することで、CRUD操作(Create, Read, Update, Delete)を簡単に実装できる点に注目しました。
また、データベース接続設定の方法やapplication.propertiesを使用した設定、schema.sqlとdata.sqlを使った初期データの準備についても詳しく解説しました。これにより、実際のアプリケーション開発に必要な準備が整います。
特に、findAllメソッドを使った全件取得や、findBy***を利用した条件付きデータ取得は、データベース操作の基本でありながら非常に強力です。これらを活用することで、SQLを直接記述することなく、効率的にデータを操作できます。
以下に、この記事で紹介したSpring Data JPAの基本的なコードをまとめます。これを参考に、実際のプロジェクトにSpring Data JPAを導入してみてください。
<!-- application.properties -->
spring.datasource.url=jdbc:mysql://localhost:3306/your_database
spring.datasource.username=root
spring.datasource.password=your_password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
<!-- 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> {
User findByUsername(String username);
}
<!-- UserServiceクラス -->
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> getAllUsers() {
return userRepository.findAll();
}
public User getUserByUsername(String username) {
return userRepository.findByUsername(username);
}
}
<!-- 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;
@Controller
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users")
public String getAllUsers(Model model) {
model.addAttribute("users", userService.getAllUsers());
return "users";
}
}
この記事を通じて、Spring Data JPAを活用した効率的なデータベース操作の方法を学べたかと思います。これらの知識を活用して、データベースを使ったJavaアプリケーション開発に挑戦してみてください。
生徒
「Spring Data JPAを使えば、SQLを書かずにデータベース操作ができるんですね!とても便利です。」
先生
「その通りです。リポジトリインターフェースを活用すれば、簡単にデータの取得や保存ができます。ただし、必要に応じてカスタムクエリも書けるので、柔軟性もありますよ。」
生徒
「データベースの初期設定や初期データの投入も簡単にできるのがいいですね。」
先生
「そうですね。schema.sqlとdata.sqlを活用することで、開発効率をさらに高めることができます。」
生徒
「次は、もっと複雑なクエリやエンティティ間の関連を学んでみたいです!」
先生
「良い目標ですね。次回はエンティティのリレーションや、カスタムクエリの作成方法について詳しく説明しましょう!」
この記事を読んだ人からの質問
プログラミング初心者からのよくある疑問/質問を解決します
Spring Data JPAとは何ですか?初心者でも使えますか?
Spring Data JPAは、JavaのSpring Frameworkでデータベース操作を簡単にするライブラリです。リポジトリインターフェースを使用することで、SQLを直接書かずにデータの取得、保存、削除が可能です。初心者でも基本的な使い方を学べば簡単に利用できます。
application.propertiesに何を設定すればデータベースに接続できますか?
application.propertiesに、データベースの接続URL(例: jdbc:mysql://localhost:3306/your_database)、ユーザー名、パスワードを設定します。また、Hibernateの設定としてspring.jpa.hibernate.ddl-autoを「update」に設定することで、データベーススキーマの自動更新も可能です。
Spring Data JPAでfindAllメソッドは何に使いますか?
findAllメソッドは、指定したエンティティクラスに基づいてデータベース内の全てのデータを取得するために使用します。このメソッドはリポジトリインターフェースに組み込まれているため、追加のSQLを書く必要がありません。
findByUsernameのようなカスタムメソッドはどうやって作るのですか?
リポジトリインターフェースで「findBy+カラム名」という形式でメソッドを定義すると、自動的にそのカラムを条件とするクエリが生成されます。例えば、findByUsernameはusernameカラムを基準にデータを取得します。
schema.sqlとdata.sqlはどのように使いますか?
schema.sqlはデータベースのテーブル構造を定義するためのファイルで、data.sqlは初期データを投入するためのファイルです。Spring Bootのプロジェクト内のsrc/main/resourcesディレクトリに配置すると、アプリケーション起動時に自動的に実行されます。
Spring Data JPAを使う場合でもSQLを直接書く必要がありますか?
基本的なCRUD操作はリポジトリインターフェースで対応できますが、複雑なクエリが必要な場合は@Queryアノテーションを使用してSQLを直接記述することもできます。
リレーショナルデータベースでSpring Data JPAはどのように動作しますか?
Spring Data JPAは、エンティティクラスとリポジトリインターフェースを基にデータベース操作を行います。エンティティクラスにはテーブルの構造を、リポジトリインターフェースには操作方法を定義し、JPAがそれを基にデータ操作を実行します。
@Autowiredは何に使うのですか?
@Autowiredは、Springコンテナに登録されたBeanを自動的に注入するために使用されます。例えば、リポジトリやサービスクラスをコントローラーで使用する際に便利です。
データベーススキーマを更新する際の注意点は何ですか?
spring.jpa.hibernate.ddl-autoを「update」に設定すると、アプリケーション起動時にスキーマが自動更新されますが、誤ってデータを上書きしたり削除しないように注意が必要です。本番環境では「validate」または「none」を推奨します。
ThymeleafとSpring Data JPAを一緒に使う利点は何ですか?
Thymeleafを使用すると、Spring Data JPAで取得したデータを簡単にテンプレートに渡してHTML上で表示できます。これにより、バックエンドとフロントエンドの統合がスムーズになります。
PageとSliceの違いは何ですか?どちらを使えば良いですか?
Pageは総件数・総ページ数などのメタ情報を含み、一覧画面のページネーションに便利です。Sliceは「次があるか」だけを持ち、総件数のカウントを行わないため軽量です。総数表示が不要ならSlice、必要ならPageを選びます。
ページ番号は0始まりですか?1始まりですか?
Spring DataのPageRequestは0始まりです。UIが1始まりの場合は、受け取ったページ番号から1を引いてPageRequest.of(page - 1, size)のように調整します。
Spring FrameworkやThymeleafを使った Webアプリ開発の全体像をやさしく理解したい人には、 この入門書が定番です。
Spring Framework超入門をAmazonで見る※ Amazonアソシエイト・プログラムを利用しています