본문 바로가기

JPA

Insert Query 줄이기(성능개선)

728x90
반응형
SMALL

Member.java

public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;
    }

Team.java

public class Team {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String teamName;

    @OneToMany(mappedBy = "team")
    private List<Member> memberList;
}

Member 와 Team은 ManyToOne 연관관계를 맺고 있다.

 

 

여기서 Member에 Insert를 하기 위해 Team의 정보를 조회해야한다.

 

@PostMapping("/test")
    public void test() {
        Long id = 1L;
        Team team = teamRepository.findById(id).get();
        Member member = Member.builder()
                .name("김영재")
                .team(team)
                .build();

        memberRepository.save(member);
    }

쿼리를 날려보면,,,

 

Hibernate: select t1_0.id,t1_0.team_name from team t1_0 where t1_0.id=?
Hibernate: insert into member (id, name, team_id) values (default, ?, ?)

먼저 Team에 대해 조회를 해온 후, member에 값을 넣어줬고 총 2번의 쿼리가 발생했다.

 

insert 쿼리를 한번 날리기 위해 연관관계로 되어있는 엔티티들을 영속성컨텍스트에 불러와 저장하는 상태가 됐다.

 

하지만 JPA 에서는 객체인데도 불구하고 DB에 들어가는값은 엔티티의 PK이다. 

 

객체 단위가 아닌, PK로 생각하면 쿼리를 줄일 수있다.

 

 

public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id" ,insertable = false, updatable = false, nullable = false)
    private Team team;

    @Column(name = "team_id")
    private Long teamId;
}

Member.java 코드를 위와 같이 수정해준다.

 

연관관계의 FK를 생성하지 않고 컬럼과 같은 이름의 필드를 만든다. 그리고 FK 참조 필드에는 insertable,updatable 모두 false 로 하여 사용을 중지시킨다.

 

@PostMapping("/test")
    public void test() {
        Long id = 1L;
        Member member = Member.builder()
                .name("김영재")
                .teamId(id)
                .build();

        memberRepository.save(member);
    }

객체가 아닌 PK 값을 넣어주고 save를 해준다.

 

쿼리를 보자

Hibernate: insert into member (id, name, team_id) values (default, ?, ?)

select 쿼리가 발생하지 않고 insert 쿼리만 발생한것을 볼수 있다.

 

pk값을 알고 있다면,

그 pk 값으로 객체단위로 조회를 해온 데이터를 저장하는 방법 보다

 

pk값을 직접 데이터에 저장해주는 방법으로 써 조회 쿼리를 줄일수있다.

 

상황에 따라 다르니 , 무조건 쓰는게 아니라 상황에 맞게 사용하자.

728x90
반응형
LIST

'JPA' 카테고리의 다른 글

Dirty Checking(더티 체킹) 이란.  (0) 2023.05.15
QueryDSL 연산자 비교식 정보  (0) 2023.05.09
N+1 문제  (0) 2023.03.16
JPQL 사용 시 DTO Mapping 하는 법  (1) 2023.02.24
Entity의 null값으로 인해 default 설정 반영이 안될 때  (0) 2022.12.14