자바 프로그래밍 8주차 학습일지

1. 학습한 내용 정리 (요약)

이번 수업에서는 Spring Data JPA의 **JPQL(@Query)**과 Query Method를 중심으로 학습하였다.
JPQL (Java Persistence Query Language)
SQL과 유사하지만 테이블이 아닌 엔티티와 필드명을 대상으로 쿼리 작성
JPA 구현체가 JPQL을 SQL로 변환 후 실행
SELECT, UPDATE, DELETE 지원 (INSERT는 엔티티 저장으로 처리)
@Query 애노테이션으로 JPQL 직접 정의 가능, 복잡한 조회/조인/서브쿼리 구현에 유리
Query Method
메서드 이름만으로 쿼리를 자동 생성
간단한 조건 조회 시 JPQL 없이 빠르게 구현 가능
키워드: And, Or, Between, LessThan, GreaterThanEqual, Like, Containing, StartingWith, EndingWith, IsNull, OrderBy, CountBy, ExistsBy, DeleteBy 등
실습 요약
JPQL 기반 CourseQueryRepository와 Query Method 기반 CourseQueryMethodRepository 구현
JPQL 직접 작성과 메서드 네이밍 방식 차이 비교 실습

2. 작성한 핵심 코드 설명 (목적 및 동작)

Course 엔티티

@Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Getter @ToString public class Course { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(unique = true, nullable = false) private String name; @Column(nullable = false) private String category; private int rating; @Column(nullable = false) private String description; public Course(String name, String category, int rating, String description) { this.name = name; this.category = category; this.rating = rating; this.description = description; } }
Java
복사
목적: JPA가 관리하는 도메인 엔티티, 테이블의 row에 대응
주요 요소: @Entity, @Id, @GeneratedValue — 엔티티 식별자 자동 생성
노트: Lombok(@Getter, @NoArgsConstructor 등) 사용 시 IDE에서 Lombok 플러그인과 annotation processing 활성화 필요

CourseQueryRepository (JPQL 사용)

public interface CourseQueryRepository extends JpaRepository<Course, Long> { @Query("SELECT c FROM Course c where c.name = :name OR c.category = :category") List<Course> findByNameOrCategory( @Param("name") String name, @Param("category") String category); }
Java
복사
목적: JPQL로 조건(name 또는 category) 조회
동작: @Query 안 JPQL 문자열을 JPA가 SQL로 변환 후 실행, @Param으로 파라미터 바인딩
사용 시기: 복잡한 조건이나 명시적 조인이 필요할 때

테스트 코드 (DataJpaTest)

@DataJpaTest class CourseQueryRepositoryTest { @Autowired private CourseQueryRepository courseQueryRepository; @Test @Sql("/insert-courses.sql") void findByNameOrCategory() { List<Course> byNameOrCategory = courseQueryRepository.findByNameOrCategory("Java Fundamentals", "Phyton"); assertThat(byNameOrCategory).extracting(Course::getCategory).contains("Java", "Phyton"); } }
Java
복사
목적: JPA 레포지토리 메서드 동작 검증
@DataJpaTest: 인메모리 DB(H2)로 JPA 계층만 테스트
주의: @Sql 경로가 올바른지 확인 필요

3. 오류 해결 과정 및 주의사항

오류 A

findAll(Example<S>) 충돌
원인: 같은 시그니처 메서드가 서로 다른 반환 타입을 가지는 클래스가 섞여 있을 때 발생 (Spring Data 라이브러리 버전 충돌)
해결 방법
1.
build.gradle / pom.xml에서 spring-boot-starter-data-jpa만 사용
2.
Gradle: ./gradlew dependencies --configuration runtimeClasspath Maven: mvn dependency:tree로 의존성 트리 확인
3.
Spring Boot 버전과 Spring Data 모듈 버전 일치 확인
4.
QueryByExampleExecutor 직접 추가 시 제거
5.
클린 빌드: ./gradlew clean build --refresh-dependencies

오류 B

Cannot resolve symbol Course
원인 가능성
1.
테스트 클래스와 Course 클래스 패키지 불일치
2.
Course 클래스 컴파일 실패
3.
Lombok 미설치/설정 문제
4.
IDE 캐시 문제
해결 방법
패키지와 import 확인
Course 클래스 컴파일 오류 수정
Lombok 플러그인 설치, annotation processing 활성화
IDE 캐시 무효화 및 재시작