728x90

재귀 알고리즘

개념을 먼저 익힌 후에 백준 알고리즘을 푸는식으로 해야겠다. 맨땅에 헤딩식으로 하면 나는 잘 이해가 안되는 것 같다. 천천히 하더라도 깊이있게 해보자❗

재귀란?

어떤 사건이 자기 자신을 포함하고 다시 자기 자신을 사용하여 정의될 때 재귀적이라고 한다.

바로 예제로 가보도록 하자

팩토리얼 구하기

재귀의 예시로 팩토리얼이 있다.
n!(팩토리얼) 은 n * n-1 * n-2 * ... 이다.
이것을 그대로 코드로 표현하면 다음과 같다.

import java.util.Scanner;

public class Factorial {
    static int factorial(int n) {
        if(n > 0)
            return n * factorial(n - 1);
        else
            return 1;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        System.out.println(n + "! = " + factorial(n));
    }
}

동작형식을 자세하게 보면 factorial(int n)은 n이 0보다 크면 n * factorial(n - 1) 를 호출하고 아니면 1을 반환한다.

풀어서 써보자.

예를 들어 n값에 3을 넣었다고 가정한다.

  • n = 3
    • 3 * factorial(2);
    • 2 * factorial(1);
    • 1 * factorial(0);
    • return 1

이 순서로 들어가게 될텐데,

맨 마지막의 1부터 1 * 2 * 3 이 되는 것이다.
호출은 n = 3부터 시작했으니 정렬이 되면 3 * 2 * 1이 되게 된다.

이렇게 해서 3! 의 답인 6을 얻게된다.

내가 재귀를 볼때 막힘없이 봐야 이해가 쏙 되는것 같은 느낌 😂

한번에 안읽히면 머릿속에서 무한루프를 도는느낌이다.

항상 끝부터 쭉 나간다음 생각해 보는것이 이해가 잘된다❗

재귀 안썼을 때

static int factorial(int n) {
        int count = 1;

        for(int i = n; i > 0; i--) {
            count *= i;
        }

        return count;
    }

유클리드 호제법

최대공약수를 재귀로 구할 수 있다.

두 정수를 직사각형 두 변의 길이라고 가정하면 최대 공약수를 구하는 문제는 다음과 같아질 수 있다.

직사각형을 정사각형으로 완전히 채우고, 만들 수 있는 정사각형의 가장 긴 변의 길이를 구하자

4와 22 의 최대 공약수를 구해보자고 가정하면

  1. 22 x 4에서 4를 한변으로 하는 정사각형으로 분할한다.
  2. 5개의 4 x 4 정사각형이 생기고 2 x 2 두개가 남는다.
  3. 이렇게 더이상 나눌 수 없는 2 x 2 정사각형이 생겼으므로 2가 최대 공약수이다.
public class Euclid {
    static int solution(int x, int y) {
        if(y == 0) {
            return x;
        }

        return solution(y, x % y);
    }

    public static void main(String[] args) {
        int x = 22;
        int y = 4;
        System.out.println(solution(x, y));
    }
}

단순하게 해석하면 0일때까지 계속 solution 자기 자신을 호출하면서 맨 마지막에 남은 x를 돌려주는 것이다.

재귀 안썼을 때

static int gcd2(int x, int y) {
        while (y != 0) {
            int temp = y;
            y = x % y;
            x = temp;
        }
        return x;
    }

배열 모든 요소의 최대 공약수

public class EucArray {

    static int euc(int x, int y) {
        while (y != 0) {
            int temp = y;
            y = x % y;
            x = temp;
        }
        return x;
    }

    static int eucArray(int[] arr, int index, int length) {
        if(length == 1) {
            return arr[index];
        }

        if(length == 2) {
            return euc(arr[index], arr[index + 1]);
        }

        return euc(arr[index], eucArray(arr, index + 1, length - 1));
    }

    public static void main(String[] args) {
        int[] arr = {3, 6, 8, 12, 15};
        System.out.println(eucArray(arr, 0, arr.length));
    }
}

막상 풀어보니까 이렇게 복잡한거는 재귀보다는 다른 방법이 나아보이는....

728x90

'CS' 카테고리의 다른 글

불 논리 회고  (0) 2022.08.07
HTTP  (0) 2022.08.07
불 논리 정리  (0) 2022.08.07
[알고리즘] 그리디  (0) 2022.08.04
728x90

포스팅이 늦었다. 3주차 미션인 사다리도 끝나게 되었다.

로또에서보다 난이도가 많이 올라간 느낌이었다.

리뷰어분이 빡세게 그리고 꼼꼼하게 해주신 덕분에 나 자체도 굉장히 성장한것 같다❗

아래는 깃허브 PR 목록이다.

사다리 1주차

사다리 2주차

사다리 3주차

사다리 4주차

테스트

전체적으로 테스트코드를 고민하다가 한번 로직에 손을 대면 저절로 도메인 위주로 구현을 하게 되었다.

테스트를 항상 생각하면서 그리고 테스트를 실행함으로 인해 로직을 구현해 나가야 하는것이 조금 부족했던 챕터였다.

그래서 중간에 리뷰를 받다가 너무 로직이 답답해 보였다.

읽고있던 이펙티브 자바를 접목시켜서 조금 더 나은 로직으로 개선했다.

로직개선으로 문제를 겪었었는데, 그 문제가 바로 절차지향으로 개발했기 때문에 문제였다.

모든 로직을 한군데에 구현해놓으니까 분리하기도 쉽지않고 어떻게 돌아가는지 명확하게 알 수도 없는 그런 로직이 완성되어 있었다.

이걸 일급 컬렉션으로 포장해주고, 모든 엔티티를 작게 유지한다 라는 조건을 생각하면서

개발하게 되니까 확실히 알기도 쉬워졌고, 유지보수성이 좋게 되었다.

무엇보다 인터페이스 그리고 람다에 대해 공부를 많이 해야겠다고 생각했다.

프로그램이 뭘 하는지 어떻게 해야하는지 생각하는 Out-In방식이 아니라

In-Out방식으로 최소한의 객체에서부터 출발하는 생각을 지속적으로 해야한다.

접근방식

처음에 내가 이 사다리를 놓고 접근한 방식은 다리와 세로 기둥을 같이 넣어서 구현하려고 했던게 문제였다.

그러니까 사다리 라는 큰 틀만 놓고 일차원적으로 생각한 결과가 이렇게 된 것이다.

여기가 갈아 엎은 부분

그래서 결국 생각해낸 것은 이라는 객체가 결국 이동해서 결과를 내주는 것인데

점부터 시작해서 왼쪽 오른쪽을 판단하게끔 로직을 구현하니까 점점 조금씩 큰 컬렉션으로 나가지면서 그에 대한 테스트도 조금씩 늘릴 수가 있게 되었다.

요구사항

참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)
pobi,honux,crong,jk

실행 결과를 입력하세요. (결과는 쉼표(,)로 구분하세요)
꽝,5000,꽝,3000

최대 사다리 높이는 몇 개인가요?
5

사다리 결과

pobi  honux crong   jk
    |-----|     |-----|
    |     |-----|     |
    |-----|     |     |
    |     |-----|     |
    |-----|     |-----|
꽝    5000  꽝    3000

결과를 보고 싶은 사람은?
pobi

실행 결과
꽝

결과를 보고 싶은 사람은?
all

실행 결과
pobi : 꽝
honux : 3000
crong : 꽝
jk : 5000

조건

자바 8의 스트림과 람다를 적용해 프로그래밍한다.

  • 규칙
    • 모든 엔티티를 작게 유지한다.
    • 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.

위 요구사항에 따라 4명의 사람을 위한 5개 높이 사다리를 만들 경우, 프로그램을 실행한 결과는 다음과 같다.

728x90

'Java' 카테고리의 다른 글

JVM  (0) 2022.08.06
Effective Java 4장 요약  (0) 2022.08.06
TDD Clean Code with Java 12기 2주차 피드백  (0) 2022.08.06
TDD Clean Code with Java 12기 2주차  (0) 2022.08.05
728x90

테스트 코드

자동차 경주에 대한 라이브 피드백 시간인데
느낀점이 있어서 포스팅하게 되었다.

테스트 코드 비교할 경우

우리는 항상 getter, setter 메소드를 많이 써왔다.
그래서 나도 습관처럼 객체를 생성하고 비교를 할 경우에 아래와 같이 코드를 작성했었다.

@Test
void create() {
    Position actual = new Position(5);
    assertThat(actual.getPosition).isEqualTo(5);
}

이런식으로 get 메소드를 사용해서 값을 비교를 했는데
이 방식은 잘못되었다기 보다는 get을 사용하지 않고
객체와 객체를 비교하는 방법을 사용하는 것이 오히려 객체지향적 측면에서 좋을 것 같다.

그렇게 Position 클래스에 equals()hashCode() 를 오버라이드 해주고 객체끼리 비교하게끔 만들어준다.

public class Position {
    private Position position = new Position(0);

    public Position(int position) {
        if (position < 0) {
            throw new IllegalArgumentException("음수는 위치 값이 될 수 없음");
        }
        this.position = position;
    }
}
@Test
void create() {
    Position actual = new Position(5);
    assertThat(actual).isEqualTo(new Position(5));
}

이렇게 객체 두개가 같은지를 구현하면 테스트가 성공하게 된다.

이런식으로 어떤 객체를 생성했을때 객체끼리 비교하는 습관을 들이도록 해보자.

문자열과 원자값을 포장해서 쓰는게 객체지향에서 하기 굉장히 좋은 것이니까 지금부터라도 습관 들이자~😄

이제서야 이펙티브 자바 1장이 이해가 되는것 같다. 경험해봐야 이해가 잘되는 이 기분이 좋다.

일급 컬렉션

필드변수를 하나만 두고 사용하는 클래스이다.

일급 콜렉션을 사용하면 계속해서 객체에게 메세지를 보내서 get메소드 대신 객체에게 위임해서 데이터를 조작하게끔 만들어야 한다.

하나씩 객체들을 포장해서 관리하면 테스트 로직을 짜기에 되게 수월하게 작성할 수 있다.

객체에 메시지를 보내라 = 객체가 하게 만들어라 = 객체에게 위임해라

클래스 역할은 작게할수록, 그리고 클래스를 잘게 쪼갠다면? TDD는 쉬워진다

항상 이것들을 생각하면서 코드를 작성하도록 하자 👍텍스트

728x90

'Java' 카테고리의 다른 글

Effective Java 4장 요약  (0) 2022.08.06
TDD Clean Code with Java 12기 3주차  (0) 2022.08.06
TDD Clean Code with Java 12기 2주차  (0) 2022.08.05
[JPA] 객체 지향 쿼리 심화  (0) 2022.08.05
728x90

로또

2주차 미션은 로또 생성기였다.


Step1 - 문자열 덧셈 계산기


Step2 - 로또(자동)


Step3 - 로또(2등)


Step4 - 로또(수동)

프로그래밍 요구사항이 점점 추가되어 조금 더 제한적인 상황에서 조건문을 사용해야 한다.
주차가 늘어가면서 느끼는것이지만, 테스트 주도 개발을 하게 되니까 안하던 방법이라서 손에 익지는 않았다. 그런데 완성되는 테스트를 먼저 구현하다 보니까 오류가 나는 상황에 대해서 더 생각하고 코드를 구현할 수 있게 되는것 같다.

이 과정을 진행하면서 이펙티브 자바도 같이 읽고 있다. 정적 팩토리 메서드는 이제 꼭 쓰게 되는것 같다.😁 꼭 쓰는것은 또 아니라고 생각해야되는데 일단 무분별하게 생성자로 객체를 생성할 수는 없게 만들어 놨다.

클래스

클래스 부분에서 좀 많은 생각을 했었고 이번 과제에서는 if조건문을 추상 클래스와 추상 메소드를 활용해서 조건문을 처리한 로직이 있다.

아직 2주차 미션임에도 불구하고 예전 코드와 좀 많이 달라졌다는게 눈에 보인다.
단순 로직만 구현을 바꾸는 것도 좋겠지만 그 안의 복잡도도 고쳐가면서 코드를 구현해 나가야겠다.

강의를 정말 신청하길 잘했다는 생각이 들고 이 과정을 완주하는것이 목표니까 최선을 다 해보도록 해야겠다.

아래는 2주차 미션의 요구사항이다.

요구사항

기능 요구사항
로또 구입 금액을 입력하면 구입 금액에 해당하는 로또를 발급해야 한다.

로또 1장의 가격은 1000원이다.
구입금액을 입력해 주세요.
14000
14개를 구매했습니다.
[8, 21, 23, 41, 42, 43]
[3, 5, 11, 16, 32, 38]
[7, 11, 16, 35, 36, 44]
[1, 8, 11, 31, 41, 42]
[13, 14, 16, 38, 42, 45]
[7, 11, 30, 40, 42, 43]
[2, 13, 22, 32, 38, 45]
[23, 25, 33, 36, 39, 41]
[1, 3, 5, 14, 22, 45]
[5, 9, 38, 41, 43, 44]
[2, 8, 9, 18, 19, 21]
[13, 14, 18, 21, 23, 35]
[17, 21, 29, 37, 42, 45]
[3, 8, 27, 30, 35, 44]

지난 주 당첨 번호를 입력해 주세요.
1, 2, 3, 4, 5, 6

당첨 통계
---------
3개 일치 (5000원)- 1개
4개 일치 (50000원)- 0개
5개 일치 (1500000원)- 0개
6개 일치 (2000000000원)- 0개
총 수익률은 0.35입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)

힌트

  • 로또 자동 생성은 Collections.shuffle() 메소드 활용한다.
  • Collections.sort() 메소드를 활용해 정렬 가능하다.
  • ArrayList의 contains() 메소드를 활용하면 어떤 값이 존재하는지 유무를 판단할 수 있다.

프로그래밍 요구사항

  • 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. 단, UI(System.out, System.in) 로직은 제외
  • 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.
  • UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.
  • indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다.
    • 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
    • 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메소드)를 분리하면 된다.
  • 함수(또는 메소드)의 길이가 15라인을 넘어가지 않도록 구현한다.
    • 함수(또는 메소드)가 한 가지 일만 잘 하도록 구현한다.
  • 모든 로직에 단위 테스트를 구현한다. 단, UI(System.out, System.in) 로직은 제외
  • 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.
  • UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.
  • 자바 코드 컨벤션을 지키면서 프로그래밍한다.
    • else 예약어를 쓰지 않는다.
    • 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
      else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.
728x90

'Java' 카테고리의 다른 글

TDD Clean Code with Java 12기 3주차  (0) 2022.08.06
TDD Clean Code with Java 12기 2주차 피드백  (0) 2022.08.06
[JPA] 객체 지향 쿼리 심화  (0) 2022.08.05
Effective Java 1장  (0) 2022.08.05
728x90

객체 지향 쿼리 심화

한번에 여러 데이터를 수정할 수 있는 벌크 연산이 있다.

벌크 연산

엔티티를 수정하려면 영속성 컨텍스트 변경 감지 기능이나 병합을 사용하고, 삭제하려면 em.remove() 를 사용한다. 데이터를 하나씩 처리하기엔 너무 오래걸려서 여러개를 동시에 처리할 수 있는 벌크연산이 있다.

벌크 연산은 executeUpdate() 를 사용한다. 이 메소드는 벌크 연산으로 영향을 받은 엔티티 건수를 반환한다.

주의사항

벌크 연산은 영속성 컨텍스트를 통하지 않고 바로 DB에 직접 쿼리를 날린다. 그래서 영속성 컨텍스트에 있는 엔티티와 DB에 있는 테이블의 칼럼 값이 다를 수 있는데, 그래서 이 부분을 주의하여야 한다.

  • em.refresh 사용
    • 엔티티를 사용해야 할 경우엔 DB에서 다시 조회한다.
  • 벌크 연산 먼저 실행
    • 벌크연산을 가장 먼저 실행하여 실행한 후에 조회쿼리를 하면 변경된 것으로 조회가 된다.
  • 벌크연산 수행 후 영속성 컨텍스트 초기화
    • 수행 직후 컨텍스트를 초기화하여 엔티티를 제거했다가 벌크연산이 적용된 DB에서 조회하는 방법

영속성 컨텍스트와 JPQL

쿼리 후 영속 상태인것과 아닌 것

select m from Member m //엔티티 조회 (영속성 O)
select o.address from Order o //임베디드 타입 조회 (영속성 X)
select m.id, m.name from Member m // 필드 조회 (영속성 X)

엔티티 전체를 조회해야만이 영속성 컨텍스트가 관리한다❗️

JPQL로 조회한 엔티티와 영속성 컨텍스트

앞선 포스팅에서 JPQL로 DB에서 조회한 엔티티가 영속성 컨텍스트에 있다면 JPQL로 DB에서 조회한 값은 버리고 영속성 컨텍스트에 있던것을 꺼내온다고 했다.

덮어쓰거나 하게 된다면 컨텍스트안에서 수정 중이었던 데이터가 사라질 수 있어 위험하다.
그래서 영속성 컨텍스트는 엔티티의 동일성을 보장하기 때문에 em.find로 조회를 하던, JPQL을 사용하던 영속성 컨텍스트가 같으면 동일한 엔티티를 반환해준다.

JPQL의 특징

  • JPQL은 항상 DB를 조회한다.
  • JPQL로 조회한 엔티티는 영속 상태이다.
  • 영속성 컨텍스트에 이미 존재하는 엔티티가 있으면 기존 엔티티를 반환한다.

그래서 영속성 컨텍스트의 1차 캐시를 되도록이면 관리하여 많이 이용하는 것이 DB에 부하를 적게 주는 것이고 그게 바람직한 사용방법인것 같다는 나의 견해? 🤔

JPQL과 플러시 모드

flush는 영속성 컨텍스트의 변경 내역을 DB에 동기화 해주는 것이다.
그래서 JPA는 flush가 발생했을 때 쓰기지연 SQL 저장소 라고 했던 저장소에 있던 쿼리들을 쭉 만들어 DB에 반영해준다. flush를 호출하려면 em.flush()를 하거나 flush 모드에 따라 커밋 직전이나 쿼리 실행 직전에 자동 호출된다.

쿼리와 플러시 모드

JPQL은 영속성 컨텍스트 데이터를 고려하지 않고 DB에서 조회하기 때문에 사용할때는 반드시 영속성 컨텍스트의 변경사항을 flush해주어야 한다. 그렇지 않으면 데이터가 섞일 수 있다.

@Test
@DisplayName("쿼리와 플러시 모드")
void queryAndFlushTest() {
    em.setFlushMode(FlushModeType.COMMIT);
    Item item = em.find(Item.class, 1L);
    item.setPrice(2000);

    Object item2 = em.createQuery("select i from Item i where i.price = 2000").getSingleResult();
    System.out.println(item2.toString());
}

flush모드를 commit시에만 플러시로 설정해놓으면

이러한 select쿼리문 후에 에러를 발생한다.


맞는 엔티티를 찾을 수 없다고 나오게 된다.

정리

  • JPQL은 SQL을 추상화하여 특정 DB에 의존하지 않는다.
  • QueryDSL은 JPQL을 만드는 빌더 역할만 하므로 JPQL을 잘 알아야 함!
  • QueryDSL을 사용하면 동적 쿼리를 생성하기가 편리하다.
  • QueryDSL은 JPA가 공식 지원하는 것은 아니지만 직관적이고 편리하다.
  • JPA도 네이티브 쿼리를 지원하지만, 종속적인 SQL을 사용하게 되면 특정 DB에만 한정적인게 된다.
    • JPQL을 최대한 활용 해보고 안되면 그 때 네이티브 SQL을 사용하자😊
  • JPQL은 대용량 수정, 삭제를 할 수 있는 벌크 연산을 지원한다.
728x90

'Java' 카테고리의 다른 글

TDD Clean Code with Java 12기 2주차 피드백  (0) 2022.08.06
TDD Clean Code with Java 12기 2주차  (0) 2022.08.05
Effective Java 1장  (0) 2022.08.05
MockMvc  (0) 2022.08.04
728x90

네이티브 SQL

JPQL은 표준 SQL이 지원하는 대부분의 문법과 SQL함수를 지원한다.
근데 특정 DB의 방언과 같은 종속적 기능은 지원하지 않는다.

  • 특정 DB만 지원하는 함수, 문법, SQL 쿼리 힌트
  • 인라인 뷰(from절 서브쿼리), UNION, INTERSECT
  • 스토어드 프로시저

종속적인 기능을 지원하는 방법은

  • 특정 DB만 사용하는 함수
    • 특정 JPQL에서 네이티브 SQL 함수를 호출할 수 있다.
    • Hibernate는 DB 방언에 각 DB에 종속적 함수를 정의했다. 그리고 직접 호출할 함수를 정의하기도 가능하다.
  • 특정 DB만 지원하는 힌트
    • Hibernate를 포함한 몇몇 JPA구현체가 지원한다.
  • 인라인 뷰(from절 서브쿼리), UNION, INTERSECT
    • JPA구현체들이 지원한다. Hibernate는 지원 ❌
  • 스토어드 프로시저
    • JPQL에서 호출 가능
  • 특정 DB만 지원하는 문법
    • 너무 유니크한 쿼리 문법은 지원하지 않는데, 이때 네이티브 SQL사용. 근데 이걸 사용할까...?

네이티브 SQL을 사용하면 엔티티를 조회할 수 있고, JPA가 지원하는 영속성 컨텍스트의 기능을 그대로 사용할 수 있다.

네이티브 SQL 사용

네이티브 쿼리 API는 3가지가 있다.

  • 결과 타입을 정의
  • 결과 타입을 정의할수 없을 때
  • 결과 매핑 사용

엔티티 조회

    @Test
    @DisplayName("네이티브 SQL 엔티티 조회")
    void nativeQueryTest() {
        String sql = "select id, name, price from item where price > ?";
        Query nativeQuery = em.createNativeQuery(sql, Item.class).setParameter(1, 100);

        List<Item> items = nativeQuery.getResultList();
    }

jdbc 사용할때와 똑같은 느낌이 든다.
근데 가장 중요한점은
SQL만 직접 사용할 뿐, JPQL을 사용할 때와 같다. 조회한 엔티티도 영속성 컨텍스트에서 관리 된다.

값 조회

값으로 조회하려면 엔티티 조회처럼 class를 같이 넣어주는게 아니라
em.createNativeQuery(sql) 를 사용하면 된다.
대신 이때 nativeQuery.getResultList() 는 Object 배열을 반환하므로
List<Object[]> 로 반환을 받아야한다.
더욱 더 JDBC같이 생겼다.

결과 매핑 사용

결과 매핑을 사용하면 엔티티 자체에 너무 많은 어노테이션 설정을 해야되므로 보편적으로 사용하지 않을 것 같다는 나의 생각이 들어있다.
그래도 정리를 해보도록 하겠다.

String sql = "select M.ID, AGE, NAME, TEAM_ID, I.ORDER_COUNT FROM MEMBER M " +
"LEFT JOIN (SELECT IM.ID, COUNT(*) AS ORDER_COUNT FROM ORDERS O, MEMBER IM " +
"WHERE O.MEMBER_ID = IM.ID) I ON M.ID = I.ID";

Query nativeQuery = em.createNativeQuery(sql, "memberWithOrderCount");
List<Object[]> members = nativeQuery.getResultList();

아래는 매핑 정의 코드이다.

@Entity
@SqlResultSetMapping(name = "memberWithOrderCount",
    entities = {@EntityResult(entityClass = Member.class) },
    columns = {@ColumnResult(name = "ORDER_COUNT")}
}
public class Member {...}

id, age, name, team_idMember 엔티티로 매핑을 시키고 order_count 는 단순 칼럼으로 매핑했다.
이렇게 여러 컬럼들을 매핑해서 추출할 수 있다.

@NamedNativeQuery

Named 네이티브 SQL을 사용하여 정적 SQL도 작성이 가능하다.
엔티티 클래스에

@NamedNativeQuery(
    name = "Member.memberSQL",
    query = "select 조회 쿼리문",
    resultClass = Member.class
)

로 등록해주고 사용하고자 하는 곳에서

TypedQuery<Member> nativeQuery = em.createNamedQuery("@NamedNativeQuery의 name", Member.class)
//파라미터가 있을 때
.setParameter();

네이티브 SQL은 휴먼에러를 발생할 확률이 QueryDSL보다 굉장히 높을 것으로 예상한다.
그래서 웬만하면 QueryDSL로 하지만 한방쿼리가 적절하게 필요할때만 사용하도록 해야할듯? 싶다. 😅
아직 실무에서 제대로 사용하지 않아서 이런 실무에서의 타협점은 점차 늘려가야 될것으로 보인다.

728x90

'JPA' 카테고리의 다른 글

JPA metamodel must not be empty!  (0) 2022.08.06
[JPA] findAll, findById 차이  (0) 2022.08.06
[JPA] 객체 지향 쿼리 언어 - Querydsl 2  (0) 2022.08.05
[JPA] 객체 지향 쿼리 언어 - Querydsl  (0) 2022.08.05

+ Recent posts