Page History
...
JPA에서 표준인터페이스가 존재하지 않으며, 네이티브 SQL로 사용하거나 JPQL을 사용하기위해서는 방언 설정이 필요하게됩니다.
어플리케이션에서 랭킹처리하기
SQL문으로 간단하게 처리할수 있고 성능적으로도 우수한, 윈도우함수 활용이 권장이 되지만
만약 사용하는 DB가 윈도우함수를 지원하지 못하고, 유사한 기능수행을 위해 성능이 느린 SQL문 작성을 요구될시
랭킹 소스는 데이터베이스로부터 Read를 하고 어플리케이션 레벨에서 랭킹을 할당하는 방식을 구현해보겠습니다.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
public class AddressAgeRank {
private String name;
private int age;
private int rank;
public AddressAgeRank(String name, int age, int rank) {
this.name = name;
this.age = age;
this.rank = rank;
}
@Override
public String toString() {
String result = String.format(
"AddressAgeRank[name='%s',age=%d,rank=%d]%n",
name, age,rank);
return result;
}
} |
랭킹에 사용되는 원본 데이터의 조건을 findByAgeBetween 을통해 10세에서 90미만의
데이터로 검색조건을 축소하였으며 이후에 sorted , map 은 랭킹을 부여한후 우리가 원하는
데이터 List로 변환하게 됩니다. 람다식을 사용한 이유는, SQL문은 절차식 코드가 아니며
어플리케이션에서도 절차식이 아닌 선언형을 사용함으로 SQL 사고방식과 유사하게 할수있고
실제 절차식 코드보다 커스텀한 데이터 변환처리를 훨씬 깔끔하게 할수가 있습니다.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
public void RankTest() {
int[] score = {Integer.MIN_VALUE};
int[] no = {0};
int[] rank = {0};
List<AddressAgeRank> ageRankList =
addressRepo.findByAgeBetween(10, 90).stream()
.sorted((a,b) -> b.getAge() - a.getAge() )
.map(p -> {
++no[0];
if (score[0] != p.getAge()) rank[0] = no[0];
return new AddressAgeRank(p.getName(),score[0] = p.getAge(), rank[0] );
})
.collect(Collectors.toList());
ageRankList.forEach(item ->{
System.out.println(item.toString());
});
} |
Expand | ||
---|---|---|
| ||
Note |
---|
윈도우 함수를 사용하지 않고, 우리가 원하는 랭킹처리를하였습니다. 항상 권장되는 방식은 아니며, SQL 영역에서는 SQL문작성을 못해서 어플리케이션에서 절차식 으로 처리하는 사고방식을 초보라고 언급하기도 합니다. 하지만 이것은 SQL방식과 유사한 식을 사용한 선언형방식이며 실제 데이터베이스 내에서 윈도우 랭크함수가 작동될 구현체를 어플리케이션에서 동일하게 구현을 하였습니다. 물론 더 스마트하고 안전하게 구현했다라고 볼수는 없으며 단일 성능이 누가 더 빠르냐? 랭킹기능을 어플리케이션이 분담하여 처리하느냐? 는 각각 다른문제이며 이러한 성능 문제에 촛첨이 맞추어줘야 한다고 봅니다. SQL문 학습과 함께, 어플리케이션에서 데이터 가공을 람다식으로 하는것은 절차식 사고방식을 벗어나 SQL작성과 비슷한 선언형 사고방식을 하는것으로 람다식을 같이 연습하는것을 추천합니다. |