Spring Data JPA를 활용하면 메소드 이름만으로도 속성 표현식을 간편하게 사용할 수 있지만
연관관계를 가진 엔티티를 다룰 때에는 몇 가지 혼란스러운 부분이 있어 이러한 부분들을 정리하고자 한다.
Spring Data JPA의 공식문서에 따르면, 속성 표현식은 관리되는 엔티티의 직접적인 속성만 참조 가능
즉, 엔터티 이름 자체가 아닌 엔터티의 실제 속성(필드) 이름을 사용해야 함
메서드 분석 알고리즘은 처음에 전체 부분을 속성으로 취급하고 도메인 클래스에서 해당 이름의 속성이 있는지 확인 → 없으면 오른쪽에서부터 camel case 기준으로 나누어 분석
모호성을 해결하기 위해, 메서드 이름에 _(underscore)를 사용하여 속성의 순회 지점을 명시적으로 정의
/*Reservation 엔티티 */
@Entity
@Getter
@Builder
@Table(name = "reservation")
@AllArgsConstructor
@NoArgsConstructor
public class Reservation {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long reservationSeq;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="user_id")
private ReservationUser user;
...
}
/* ReservationUser 엔티티 */
@Entity
@Getter
@SuperBuilder
@Table(name = "user", catalog = "kcip")
@AllArgsConstructor
@NoArgsConstructor
public class ReservationUser extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long seq;
...
}
엔티티의 직접적인 속성만 참조 가능
Reservation 안에 있는 ReservationUser의 seq를 찾고싶다면 findByReservationUserSeq 가 아닌 findByUserSeq(Long empId)
먼저 Reservation에 userSeq 라는 속성이 있는지 탐색 → X
만약 ReservationUser에 seq가 아닌 다른 값이였다면 오류가 발생
모호성을 해결하기 위해 언더 스코어를 사용하여 작성하기도 함
@Repository
public interface ReservationRepository extends JpaRepository<Reservation, Long> {
Optional<CoreReservation> findByReservationSeq(Long reservationSeq);
Optional<CoreReservation> findByUserSeq(Long empId); //findByUser_Seq(Long empId)도 동일
}
결론
- 속성 표현식은 관리되는 엔티티의 직접적인 속성만 참조 가능
- 엔티티 자체가 아닌 속성(필드) 이름을 사용
- 표준 Java 네이밍 규칙에 따라 _ 는 예약된 문자로 취급
- _ 대신 camel case를 사용
참고자료
스프링JPA 공식 문서