JPA를 통한 CRUD

Red Culture·2021년 6월 29일

Create

JpaRepository를 상속받은 UserRepository 인터페이스의 싱글턴 객체를 선언한다. 생성하고자 할 테이블에 대한 객체를 생성하고 컬럼 값들에 대해 set하고, save() 메서드를 호출하면 DB에 저장이 된다.

    @Autowired
    private UserRepository userRepository;

    @Test
    public void create() {
        User user = new User();

        // user.setId(10); Id는 Auto increment 이므로 set 하지 않아도된다.
        user.setAccount("TestUser03");
        user.setEmail("TestUser03@gmail.com");
        user.setPhoneNumber("010-1111-3333");
        user.setCreatedAt(LocalDateTime.now());
        user.setCreatedBy("TestUser3");

        User newUser = userRepository.save(user);
        System.out.println("newUser : " + newUser);
    }

Read

    @Test
    public void read() {
        Optional<User> user = userRepository.findById(2L);

        // selectUser가 있으면 값을 출력
        user.ifPresent(selectUser -> {
            System.out.println("user : " + selectUser);
            System.out.println("email : " + selectUser.getEmail());
        });
    }

Update

쿼리문을 통해 특정 사용자를 select 하고 Id를 가지고 한 번 더 select 대상을 찾고 그 값에 대해 update를 실행한다. findById(2L)로 특정 사용자 Id를 선택하고 값을 update 했지만, jpa에서는 기존에 있는 selectUser를 대상으로 값을 한 번 더 꺼낸 다음에 처음에 셋팅하고자 했던 값과 더불어 기존의 있는 객체의 로우도 update 한다.

    @Test
    public void update(){

        // findById에서 2L (id가 2번인 아이디에 해당하는 것을 업데이트)
        Optional<User> user = userRepository.findById(2L);

        user.ifPresent(selectUser -> {
            selectUser.setAccount("PPPP");
            // selectUser.setId(3L);   // 3L로 셋팅하고 해당 아이디에 업데이트
            selectUser.setUpdatedAt(LocalDateTime.now());
            selectUser.setUpdatedBy("update method()");

            userRepository.save(selectUser);
        });

    }
Hibernate: select user0_.id as id1_0_0_, user0_.account as account2_0_0_, user0_.created_at as created_3_0_0_, user0_.created_by as created_4_0_0_, user0_.email as email5_0_0_, user0_.phone_number as phone_nu6_0_0_, user0_.updated_at as updated_7_0_0_, user0_.updated_by as updated_8_0_0_ from user user0_ where user0_.id=?
Hibernate: select user0_.id as id1_0_0_, user0_.account as account2_0_0_, user0_.created_at as created_3_0_0_, user0_.created_by as created_4_0_0_, user0_.email as email5_0_0_, user0_.phone_number as phone_nu6_0_0_, user0_.updated_at as updated_7_0_0_, user0_.updated_by as updated_8_0_0_ from user user0_ where user0_.id=?
Hibernate: update user set account=?, created_at=?, created_by=?, email=?, phone_number=?, updated_at=?, updated_by=? where id=?

Delete

@Test
public void delete() {
    Optional<User> user = userRepository.findById(1L);

    // user.isPresent()가 true이어야함
    Assertions.assertTrue(user.isPresent());

    user.ifPresent(selectUser -> {
        // selectUser.setId(3L);   // 3L로 셋팅하고 해당 아이디를 삭제
        userRepository.delete(selectUser);
    });

    // 삭제가 잘 되었는지 확인
    Optional<User> deleteUser = userRepository.findById(1L);

    Assertions.assertFalse(deleteUser.isPresent());     // 삭제되었으면 isPresent()가 false
}

매번 데이터를 지우다 보면 결국 DB에 데이터가 남아 있지 않게 되는데.. 테스트에 번거로움이 있지 않을까?..
-> @Transactional 어노테이션을 붙여서 DB에 있는 쿼리를 실행시키더라도 마지막에 롤백을 해준다. (Rolled back transaction for test)

Entity를 JpaRepository에서 가져올 때 주의 사항

1) Entity를 JpaRepository에서 가져올 때 기본 생성자는 필수이다.
2) 기본 생성자의 접근 제어자를 private으로 하면, 추후에 Lazy Loading 사용 시 Proxy 관련 예외가 발생할 수 있다.
3) Entity의 기본 생성자는 public 혹은 protected로 선언하는 것이 좋다.

*참고 자료
https://wbluke.tistory.com/6

profile
자기 개발, 학습 정리를 위한 블로그

0개의 댓글