터미널 창에 SQL 쿼리를 예쁘게 정렬해서 보여주는 설정이다.
application.yml 파일에 추가해주자.
spring:
jpa:
properties:
hibernate.format_sql: true
터미널 창을 clear 하기 위해서는
Ctrl + Shift + A 커맨드 팔레트를 열어서
terminal:clear를 검색해줘야 한다.
과정이 귀찮으니까 오른쪽 설정 아이콘을 눌러 단축키를 설정해주자.
키 바인딩 빈칸을 더블클릭해
원하는 단축키를 설정해주면 된다.
Ctrl + Shift + C로 설정해주었다.
이제 서버를 시작시키고 메인 페이지에 들어가 보면
post를 findAll( ) 하는데
이때 터미널 창에서 쿼리를 확인해보자.
post만 SELECT 해오는 게 아니라
user까지 SELECT 하여 총 3번의 SELECT가 발생했다.
왜 user까지 찾아온 것일까?
post 테이블에 user 오브젝트가 연관되어 있기 때문이다.
(1)
지금 메인 페이지의 디폴트 전략은
post테이블의 글을 다 들고 오고
글을 쓴 1번, 2번 user 정보를 다 들고 왔다.
1. SELECT * FROM post
2. user SELECT
3. user SELECT
만약 1000명의 유저가 있으면
모든 글을 다 들고 오고,
1000명의 유저 select를 1000번 할 것이다.
성능이 좋지 않은 쿼리이다.
(2)
유저의 정보가 필요하다면
post와 user를 조인을 사용해 한번에 들고 올 수도 있겠다.
SELECT *
FROM post p left outer join user u
on p.userId = u.id;
(3)
하지만 우리가 만드는 블로그의 메인 페이지에는
뿌려줄 유저 정보가 없기 때문에
user을 SELECT 할 필요가 없다.
그냥 post만 SELECT 하면 되겠다.
SELECT * FROM post;
그렇다면 왜 디폴트가 첫 번째 쿼리일까?
일단 user 정보까지 가져와놓으면 사용하고 싶을 때 사용할 수 있기 때문이다.
메서드를 만들어주는 JPA 입장에서는 사용하는 사람이
user까지 사용할 수도 있다고 생각하면서 만들 수밖에 없다.
사용하지 않으면 그냥 안 쓰면 그만인데
필요할 수도 있기 때문에 가져와주는 것이다.
쿼리의 성능은 좋지 않아도 사용하는 사람에게 자유도를 주는 것이다.
JPA를 상속받아 사용한다고 하더라도
어떤 쿼리가 내 페이지에 제일 좋은지 알아야 뜯어고칠 수 있다.
제일 좋은 쿼리가 (3) post만 가져오는 거라고 생각했으면
바꿀 수도 있어야 한다.
post만 SELECT 하고 싶어서 findAll( ) 메서드를 사용하지 않고
mFindAll( ) 메서드를 만들어보았다.
package site.metacoding.dbproject.domain.post;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
@Repository
public interface PostRepository extends JpaRepository<Post, Integer> {
@Query(value = "SELECT * FROM post", nativeQuery = true)
Post mFindAll();
}
그리고 메인 페이지 메서드에서 findAll( )이 아닌
mFindAll( ) 메서드를 호출해보자.
그래도 결과는 같았다.
post에 user 오브젝트가 연관되어 있기 때문이다.
오브젝트가 연관되어 있으면
자동으로 SELECT 한다.
글 상세보기 페이지에서는 어떤 쿼리가 나올까?
자동으로 post와 user가 조인하여 실행되었다.
나는 post만 SELECT 했는데 JPA가 조인까지 해준 것이다.
하나씩 확인해보며 알 수 있는 쿼리 기본전략이 있다.
1. post 전체를 SELECT 하면 (SELECT * FROM post)
- post를 다 가져오고
- post를 다 가지러 갔더니 User 오브젝트도 필요하네?
각각의 User 오브젝트 SELECT
2. 하나의 post SELECT 하면
- post, user를 조인해서 가져온다.
∴ 하나의 값을 가져올 때는 조인해서 가져오고
전체를 가져올 때는 한방에 가져왔다가 필요한 만큼 다시 하나씩 쏙쏙 찾아준다.
이런 쿼리 전략을 바꾸기 위해서는 JPA Fetch 전략을 알아야 한다.
[출처]
https://cafe.naver.com/metacoding
메타 코딩 유튜브
https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9