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);
}
@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());
});
}
쿼리문을 통해 특정 사용자를 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=?
@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)
1) Entity를 JpaRepository에서 가져올 때 기본 생성자는 필수이다.
2) 기본 생성자의 접근 제어자를 private으로 하면, 추후에 Lazy Loading 사용 시 Proxy 관련 예외가 발생할 수 있다.
3) Entity의 기본 생성자는 public 혹은 protected로 선언하는 것이 좋다.
*참고 자료
https://wbluke.tistory.com/6