Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
Tags
- Java데이터 타입
- While
- 시스템 환경 변수 편집
- Java
- continue문
- 접근제어지시자
- 컴파일
- 반복문
- 자바 멀티스레딩
- JAVA기초
- java변수
- 집합관계
- 연관관계
- IntelliJ IDEA
- for문
- 메서드
- break문
- 인텔리제이 기초 설정
- 상수
- 생성자
- function
- OPP개념
- 메서드 오버로딩
- 형 변환
- 포함관계
- multi-threading
- 인텔리제이 한글 깨짐 해결법
- this예약어
- JAVA객체지향
- Thread
Archives
- Today
- Total
최원종의 개발 블로그
스프링부트 V5 JPARepository + Service(JpaRepository 인터페스와 Optional 타입) 본문
Spring boot 입문
스프링부트 V5 JPARepository + Service(JpaRepository 인터페스와 Optional 타입)
chl6698 2026. 5. 19. 17:38
JpaRepository 개념
Spring Data JPA에서 제공하는 인터페이스로, 기본적인 CRUD 메서드들을 자동으로 제공
- 기존의 EntityManager를 직접 사용하는 방식에서 더 간편한 방식으로 발전
- findAll(), save(), findById(), deleteById() 등의 메서드를 자동 제공
- 복잡한 쿼리는 @Query 어노테이션으로 직접 작성 가능
BoardRepository → JpaRepository 인터페이스 활용
@Repository 명시 생략 가능 : JpaRepository 인터페이스 상속 시 스프링이 자동으로 빈(Bean) 등록 수행
기본 제공 CRUD 메서드 : save()(등록/수정), findById()(단건조회), findAll()(전체조회), deleteById()(삭제)
findByIdJoinUser() : 게시글 ID로 상세 조회 시 fetch join을 통해
작성자(User) 정보까지 쿼리 1번으로 묶어서 가져옴
findAllJoinUser() : 전체 게시글 목록을 최신순(b.id DESC)으로 조회하면서
작성자 정보까지 한방 쿼리로 낚아챔
데이터 수정 (더티 체킹) : Repository에 별도 쿼리 없이 @Transactional 안에서
엔티티 객체 값만 바꾸면 자동으로 수정 쿼리 실행
BoardRepository → JpaRepository 코드
package com.tenco.blog.board;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
import java.util.Optional;
/**
* Board 엔티티에 대한 JPA Repository 인터페이스 (클래스 아님!)
* 게시글과 관련된 데이터 베이스 접근을 담당하게 됨
* 기본적인 CRUD 이미 제공 됨.
*/
// @Repository // IoC - 굳이 명시할 필요 없음 ( JpaRepository 인터페이스를 상속했기 때문에 두번 선언할 필요 없음)
public interface BoardRepository extends JpaRepository<Board, Integer> {
// 1. 등록 및 수정 save(Board entity)
// 2. 단건 조회 : findById(Integer id)
// 3. 전체 조회 : findAll()
// 4. 삭제 : deleteById(Integer id)
// 5. 데이터 개수: count()
// 6. 존재 여부 확인: existsById(Integer id)
// 단건 조회
// 1. 게시글 ID로 조회시 사용자 정보도 함께 가져오기
@Query("""
SELECT b FROM Board b JOIN FETCH b.user WHERE b.id = :id
""")
Optional<Board> findByIdJoinUser(@Param("id") Integer id);
// 2. 전체 게시글 조회 (단 한번에 작성자 정보도 조회)
@Query("""
SELECT b FROM Board b JOIN FETCH b.user ORDER BY b.id DESC
""")
List<Board> findAllJoinUser();
// 3. 데이터 수정은 더티 체킹으로 처리
}
UserRepository → JpaRepository 인터페이스 활용
@Repository 명시 생략 : JpaRepository를 상속하면 스프링 부트가 뜰 때 자동으로 IoC 빈(Bean)으로 등록됨
기본 제공 CRUD 기능 : save()(등록/수정), findById()(단건조회),
findAll()(전체조회), deleteById()(삭제), count()(개수)
findByUsername() : 회원가입 시 아이디 중복 체크를 위해 JPQL을 사용해
특정 username을 가진 유저를 단건 조회
findByUsernameAndPassword() : 로그인 시 아이디와 비밀번호가 일치하는 회원이 존재하는지
검증하는 로그인 전용 쿼리
회원 정보 수정 (더티 체킹) : 리포지토리에 별도의 수정 쿼리 메서드 없이
영속성 컨텍스트의 감시(변경 감지) 기능을 통해 처리
UserRepository → JpaRepository 코드
package com.tenco.blog.user;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.Optional;
// @Repository -> JpaRepository 상속하고 있기 때문에 두번 작성할 필요 없음
public interface UserRepository extends JpaRepository<User, Integer> {
// 1. 사용자 등록 및 수정 : save(User user)
// - 새로운 사용자를 Insert 하거나, 기존 사용자 정보를 UPDATE 합니다.
// 2. 사용자 단건 조회: findById(Integer id)
// - PK(id) 를 통해 특정 사용자를 조회하며 Optional<User>를 반환
// 3. 전체 사용자 목록 조회 : findAll()
// - DB에 저장된 모든 사용자 정보를 List<User> 형태로 가지고 온다.
// 4. 사용자 삭제: deleteById(Integer id)
// - 특정 ID를 가진 사용자를 삭제합니다.
// 5. 데이터 갯수 : count()
// - 전체 레코드 수 반환
// 6. 존재 여부 확인 : existsById(Integer id)
// - 해당 ID를 가진 데이터가 있는지 확인하여 boolean을 반환
// 사용자명으로 사용자 조회(중복 체크 확인용)
@Query("""
SELECT u FROM User u WHERE u.username = :username
""")
Optional<User> findByUsername(@Param("username") String username);
// 사용자명과 비밀번호로 사용자 조회(로그인용)
@Query("""
SELECT u FROM User u WHERE u.username = :username AND u.password = :password
""")
Optional<User> findByUsernameAndPassword(@Param("username") String username,
@Param("password") String password);
// 사용자 정보 수정
// [더티 체킹이란?]
// 트랜잭션 내에서 조회된 객체상태를 변경하면
// 트랜잭션이 끝나는 시점에 JPA가 변경된 내용을 자동으로 감시하여
// DB에 UPDATE 쿼리를ㄹ 날려주는 기능을 말한다.
}
Optional 방식
전통적인 null 체크 방식 : 객체가 null인지 if문으로 직접 검사.
코드가 길어지고 실수로 null 체크를 빼먹으면 런타임 에러(NPE) 발생 위험
Optional 익명 클래스 방식 : JpaRepository가 반환한 Optional 객체의 orElseThrow() 메서드 활용.
내부적으로 Supplier 인터페이스를 직접 구현
Optional 람다 표현식 방식 : 익명 클래스의 불필요한 코드를 생략하고
핵심 로직인 () -> 예외생성 문법만 남겨 가독성을 극대화한 현대적 스타일
Optional예시 코드
// null 체크 방식
public Board getBoardOrThrow(Long boardId) {
Board board = boardJPARepository.findByIdJoinUser(boardId);
if (board == null) {
throw new RuntimeException("게시글을 찾을 수 없습니다.");
}
return board;
}
// Optional 방식 (익명 클래스 사용)
public Board getBoardOrThrow(Long boardId) {
return boardJPARepository.findByIdJoinUser(boardId)
.orElseThrow(new Supplier<RuntimeException>() {
@Override
public RuntimeException get() {
// 게시글이 없을 경우 예외를 생성해 반환
return new RuntimeException("게시글을 찾을 수 없습니다.");
}
});
}
// Optional 방식
// - 람다 표현식 사용 코드
public Board getBoardOrThrow(Long boardId) {
return boardJPARepository.findByIdJoinUser(boardId)
.orElseThrow(() -> new RuntimeException("게시글을 찾을 수 없습니다."));
}
'Spring boot 입문' 카테고리의 다른 글
| 스프링부트 V6- OSIV (0) | 2026.05.20 |
|---|---|
| V5-2 서비스 계층 만들어 보기 (BoardService, UserService) + 리팩토링 (0) | 2026.05.20 |
| Spring Boot 필수 어노테이션(Annotation) 총정리 (0) | 2026.05.18 |
| V4-3 intercepter 활용 (인증검사 공통 처리) (0) | 2026.05.18 |
| V4-2 에러 컨트롤러 및 커스텀 예외 처리 (@ControllerAdvice 활용) (0) | 2026.05.18 |
