ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|---|
|
@Repository の役割
@Repository は次の 3 つの役割を持ちます:
- Bean 登録(
@Componentと同じ) - 意味付け: 「これは DAO 層のクラス」と明示
- 例外変換: JDBC / JPA の例外を
DataAccessException階層(Spring 標準)に変換
基本的な使い方
① 手書き DAO
@Repository
public class UserRepository {
private final JdbcTemplate jdbc;
public UserRepository(JdbcTemplate jdbc) {
this.jdbc = jdbc;
}
public User findById(Long id) {
return jdbc.queryForObject(
"SELECT id, name FROM users WHERE id = ?",
new BeanPropertyRowMapper<>(User.class),
id
);
}
public int save(User user) {
return jdbc.update(
"INSERT INTO users (name) VALUES (?)",
user.getName()
);
}
}
② Spring Data JPA のインタフェース
// インタフェースだけ書く(実装は Spring が自動生成)
@Repository // 省略しても認識される (Spring Boot)
public interface UserRepository extends JpaRepository<User, Long> {
// メソッド名から SQL を自動生成
Optional<User> findByEmail(String email);
List<User> findByStatusOrderByCreatedAtDesc(String status);
long countByStatus(String status);
// カスタムクエリ
@Query("SELECT u FROM User u WHERE u.email LIKE %:keyword%")
List<User> searchByEmail(@Param("keyword") String keyword);
// 更新クエリ
@Modifying
@Query("UPDATE User u SET u.status = :status WHERE u.id = :id")
int updateStatus(@Param("id") Long id, @Param("status") String status);
}
例外変換の効果
@Repository が付いていると、Spring の PersistenceExceptionTranslationPostProcessor が例外を変換します:
// 変換前 (生の SQLException や Hibernate 例外)
java.sql.SQLException: Duplicate entry 'user@example.com' for key 'users.email_unique'
// 変換後 (DataAccessException 階層)
org.springframework.dao.DuplicateKeyException
extends DataIntegrityViolationException
extends NonTransientDataAccessException
extends DataAccessException
extends RuntimeException
これによって:
- RuntimeException 化:
throws SQLException等を書かなくて済む(checked → unchecked) - DB 非依存: MySQL でも PostgreSQL でも同じ例外クラスでハンドリング
- サブクラス階層が利く:
catch(DataIntegrityViolationException)で UNIQUE 違反等を一括キャッチ
主な DataAccessException
| 例外 | 意味 |
|---|---|
EmptyResultDataAccessException | queryForObject で結果が 0 件 |
IncorrectResultSizeDataAccessException | queryForObject で複数件 |
DuplicateKeyException | UNIQUE 制約違反 |
DataIntegrityViolationException | 制約違反(NOT NULL / FK / CHECK) |
DeadlockLoserDataAccessException | デッドロック |
QueryTimeoutException | クエリタイムアウト |
BadSqlGrammarException | SQL 構文エラー |
OptimisticLockingFailureException | 楽観ロック失敗(@Version 使用時) |
PessimisticLockingFailureException | 悲観ロック失敗 |
例外ハンドリング例
@Service
public class UserService {
private final UserRepository userRepository;
public User register(User user) {
try {
return userRepository.save(user);
} catch (DuplicateKeyException e) {
throw new BusinessException("このメールアドレスは既に登録済みです");
} catch (DataIntegrityViolationException e) {
throw new BusinessException("入力データに問題があります: " + e.getMessage());
} catch (DataAccessException e) {
log.error("DB エラー", e);
throw new SystemException("システムエラーが発生しました");
}
}
}
@Repository vs @Service vs @Component
| アノテーション | 用途 | 特殊機能 |
|---|---|---|
@Component | 汎用 Bean | ― |
@Service | ビジネスロジック | 意味付けのみ |
@Repository | データアクセス | 例外変換 |
JPA Repository での自動実装
Spring Data JPA を使うと、インタフェースだけ書けば実装は自動生成されます:
// インタフェース宣言
public interface UserRepository extends JpaRepository<User, Long> { }
// Spring が自動でプロキシ実装を生成
// 主要メソッドが利用可能:
userRepository.save(user);
userRepository.findById(id);
userRepository.findAll();
userRepository.deleteById(id);
userRepository.count();
userRepository.existsById(id);
// 派生クエリ (Method Name Query)
List<User> findByName(String name);
List<User> findByStatusAndCreatedAtBetween(String status, LocalDateTime from, LocalDateTime to);
Page<User> findByName(String name, Pageable pageable);
// @Query で JPQL / Native SQL
@Query("SELECT u FROM User u WHERE u.email = ?1")
Optional<User> findByEmailCustom(String email);
@Query(value = "SELECT * FROM users WHERE email = ?1", nativeQuery = true)
Optional<User> findByEmailNative(String email);
関連記事
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページ
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- 【django】ログイン 認証機能 2026-09-08 03:22:09
- MySQL ERROR 1063 Incorrect column specifier for column|原因と直し方 2026-09-08 03:11:09
- 【PHPエラー】Object of class stdClass could not be converted to string 2026-09-07 07:46:04
- Julia Genie ローカル開発サーバ起動完全ガイド 2026-09-07 07:46:04
- Wi-Fi とは|規格と世代(Wi-Fi 4〜7)・周波数帯・CSMA/CA・WPA3 NEW 2026-09-07 07:45:13
- set コマンドでシェルオプションと位置パラメータを操作 | bash 2026-09-07 07:45:13
- JPEG(.jpg/.jpeg)画像形式の完全ガイド — 仕様・マジックナンバー・他形式との比較・EXIF 2026-09-07 07:45:13
- UE5 Get Overlapping Actorsで特定クラスだけ処理|Class Filter・Cast To 2026-09-07 07:45:13
- Linuxで特定拡張子のファイルを再帰削除|find -deleteの安全手順 2026-09-07 07:45:13
- Django CBVでテンプレートに値を渡す|get_context_data・extra_context 2026-09-07 07:45:13
- Linuxで複数ファイルの文字列を一括置換|find・sed・xargsの安全手順 2026-09-07 07:45:13
- Laravelルートグループ|prefix・middleware・nameで一括管理 2026-09-07 07:45:13
- Linux whichコマンドの使い方|絶対パス取得とtype・command -vの違い 2026-09-07 07:45:13
- Linux catコマンドの使い方|行番号表示・複数ファイル連結 2026-09-07 07:45:13
- unable to execute 'gcc': No such file or directory 2026-09-07 07:45:13
コメントを削除してもよろしいでしょうか?