Spring + Boot

JPA 조회 / 수정 / 삭제 테스트

devRachel 2021. 4. 8. 14:31
@Test
    public void testSelect(){
        Long mno = 100L;
        Optional<Memo> result = memoRepository.findById(mno);
        System.out.println("==========================================");
        if(result.isPresent()){
            Memo memo = result.get();
            System.out.println(memo);
        }
    }

조회 테스트는 findById()나 getOne()을 이용해서 엔티티 객체를 조회할 수 있습니다. findById()와 getOne()은 동작하는 방식이 다른데 데이터베이스를 먼저 이용하는지, 나중에 필요한 순간까지 미루는 방식을 이용하는지에 대한 차이가 있습니다.

findById()는 java.util 패키지의 Optional 타입으로 반환되기 때문에 한번 더 결과가 존재하는지를 체크하는 형태로 작성하게 됩니다. 

 

실행시 로그

 

Hibernate: 
    select
        memo0_.mno as mno1_0_0_,
        memo0_.memo_text as memo_tex2_0_0_ 
    from
        tbl_memo memo0_ 
    where
        memo0_.mno=?
==========================================
Memo(mno=100, memoText=테스트_____100)

findById()를 실행했을 때 SQL처리가 되는 것을 볼 수 있고, "====="부분은 SQL 실행 이후 실행된 것을 볼 수 있습니다. getOne()은 @Transactional 어노테이션이 추가적으로 필요합니다. 이름에서 보면 알 수 있듯이 트랜잭션 처리를 위해 사용하는 어노테이션입니다.

 

@Transactional
    @Test
    public void testSelect2(){

        Long mno = 100L;
        Memo memo = memoRepository.getOne(mno);

        System.out.println("======================");
        System.out.println(memo);
    }

 

 실행한 로그

 

 

======================
Hibernate: 
    select
        memo0_.mno as mno1_0_0_,
        memo0_.memo_text as memo_tex2_0_0_ 
    from
        tbl_memo memo0_ 
    where
        memo0_.mno=?
Memo(mno=100, memoText=테스트_____100)

 

getOn()은 리턴 값은 해당 객체이지만 실제 객체가 필요한 순간까지 SQL을 실행하지 않습니다. getOne()을 호출할 때 "======="가 먼저 실행되고 print문이 실행되면서 실제 객체를 사용하는 순간에 SQL이 동작되는 것을 알 수 있습니다.

 

 @Test
    public void testUpdate() {
        Memo memo = Memo.builder().mno(100L).memoText("Update Text").build();

        System.out.println(memoRepository.save(memo));
    }

수정은 등록과 동일하게 save()를 이용해서 처리합니다. 내부적으로 해당 엔티티의 Id값이 일치하는지를 확인해서 insert/update 처리를 하는 것입니다.

100번 mno에 Memo 객체를 만들어서 save()를 호출하고 있지만 select 쿼리로 해당 번호의 Memo 객체를 확인하고 난 뒤 update 처리하는 것을 확인할 수 있습니다.

Hibernate: 
    select
        memo0_.mno as mno1_0_0_,
        memo0_.memo_text as memo_tex2_0_0_ 
    from
        tbl_memo memo0_ 
    where
        memo0_.mno=?
Hibernate: 
    update
        tbl_memo 
    set
        memo_text=? 
    where
        mno=?
Memo(mno=100, memoText=Update Text)

 

 

JPA는 엔티티 객체들을 메모리 상에 보관하려고 하기 때문에 특정한 엔티티 객체가 존재하는지 확인하는 select가 먼저 실행되고 해당 @Id를 가진 엔티티 객체가 있다면 update, 그렇지 않으면 insert를 실행하게 됩니다.

 

 

 

삭제테스트는 삭제하려는 번호mno가 있어야겠죠 ? 그 번호가 있는지 먼저 확인한 뒤 삭제처리를 진행합니다.

 

 @Test
    public void testDelete(){
        Long mno = 100L;
        memoRepository.deleteById(mno);
    }

 

 

리턴타입이 void이기 때문에 존재하지 않으면 EmptyResultDataAccessException 예외를 발생시킵니다. 

실행 결과

 

 

Hibernate: 
    select
        memo0_.mno as mno1_0_0_,
        memo0_.memo_text as memo_tex2_0_0_ 
    from
        tbl_memo memo0_ 
    where
        memo0_.mno=?
Hibernate: 
    delete 
    from
        tbl_memo 
    where
        mno=?