본문 바로가기
TIL

Plmography 프로젝트 작업 로그 #44 - JPA 에서 상위 n 개 데이터 찾을 때 (23.02.03 TIL)

by winteringg 2023. 2. 3.

JPA 는 아래처럼 다양한 쿼리 메서드를 제공한다.  

키워드 샘플 JPQL
Distinct findDistinctByLastnameAndFirstname select distinct …​ where x.lastname = ?1 and x.firstname = ?2
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is, Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull, Null findByAge(Is)Null … where x.age is null
IsNotNull, NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection<Age> ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection<Age> ages) … where x.age not in ?1
TRUE findByActiveTrue() … where x.active = true
FALSE findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstname) = UPPER(?1)


만약 이 메서드들 중에서도 원하는 쿼리문을 뽑아낼 수 없으면 @Query 어노테이션을 사용해서 JPQL 을 작성하면 된다. 나는 데이터 중 상위 3개의 데이터만을 가져오는 쿼리를 만들고 싶었는데, JPQL 로 작성할 까 하다가 SQL 을 배울 때 LIMIT 으로 제한된 데이터를 가져온 게 생각나서 검색해 보았다. 

검색 결과 LIMIT 은 JPA 에서는 제공하지 않고 그 대신 MySql 문법인 Top(n) 은 가능하다는 것을 알게 됐다.

Hit 이라는 필드 변수를 값객체로 만들었기 때문에 나의 경우는 아래처럼 작성하면 된다! 

// Hit class
@Embeddable
public class Hit {
    @Column(name = "hit")
    private Long value;

    public Hit() {
    }

    public Hit(Long value) {
        this.value = value;
    }

    public Long getValue() {
        return value;
    }


// Theme class
@Entity
public class Theme {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Embedded
    private Hit hit;

    @Embedded
    private Title title;
    
    
// ThemeRepository
public interface ThemeRepository extends JpaRepository<Theme, Long> {
    List<Theme> findTop3ByOrderByHit_ValueDesc();
}

 

참고 : 

 

Spring Data JPA - Reference Documentation

Example 119. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del

docs.spring.io

 

댓글