TIL (0417) JPA

UihyunLee·2025년 4월 17일

JPA를 사용하여 Service를 개발하던 중에 특정 Id의 게시글을 조회해서 삭제를 하려고 하였습니다.
기본적인 생각으로는 우선 데이터가 존재하는지 확인 => 삭제 하는 형식이 당연히 맞다고 생각을 하였기에 코드를 아래와 같이 작성했습니다.

@Transactional
public void deleteBoard(int boardId) {
	Optional<Board> board = boardRepository.findById(boardId);
    
    
    if (board.isPresent()) {
    	boardRepository.deleteById(boardId);
    }
}

그런데 코드를 작성하다보니 JPA에는 delete와 deleteById라는 두가지 방법이 있는 걸 발견했습니다. 물론 매개변수는 다릅니다.
delete(Entity)
deleteById(Integer)
하지만 매개변수 차이만으로 불필요하게 하나면 충분한 것을 두가지나 넣을 필요는 없겠죠?
나눠서 확인해보겠습니다.

deleteById

	@Override
	@Transactional
	public void deleteById(ID id) {

		Assert.notNull(id, ID_MUST_NOT_BE_NULL);

		findById(id).ifPresent(this::delete);
	}
  • findById 를 통해서 조회

delete


	@Override
	@Transactional
	@SuppressWarnings("unchecked")
	public void delete(T entity) {

		Assert.notNull(entity, ENTITY_MUST_NOT_BE_NULL);

		if (entityInformation.isNew(entity)) {
			return;
		}

		if (entityManager.contains(entity)) {
			entityManager.remove(entity);
			return;
		}

		Class<?> type = ProxyUtils.getUserClass(entity);

		// if the entity to be deleted doesn't exist, delete is a NOOP
		T existing = (T) entityManager.find(type, entityInformation.getId(entity));
		if (existing != null) {
			entityManager.remove(entityManager.merge(entity));
		}
	}
  • delete에도 자세히보면 entityManager.contains라는 메서드를 사용한 것이 보입니다. 그러나 이것은 실제 DB에 있는지 확인하는 것이 아닌 영속성 검사를 하는 것입니다.

따라서 deleteById를 할 때는 내가 기존에 작성했던 것처럼 findById 검사를 할 필요가 없는 것을 알 수 있습니다.

이럴 고려해서 추가적으로 코드를 작성해보다가 뭔가 이상함을 깨달았습니다.당연히 deleteById를 사용하면 조회가 되고 삭제가 되기에 조회를 했을 때 없으면 Exception이 발생해야하는게 아닌가라는 생각이 들었고 테스트를 해봤다.

boardRepository.deleteById(boardId);
이 코드를 사용해서 테스트를 해봤는데 id가 존재하지 않는 데이터를 삭제하려고 요청을 보내도 Exception이 뜨지 않습니다.
생각해보면 당연한 결과인데, deleteById 내부 코드를 봤을 때 findById로 확인후 존재한다면 delete 메서드를 사용하는 것이기 때문입니다. 그렇다면 findById에는 자동으로 예외처리를 해줄까요?
만약 그랬다면 OptionalisPresent 메서드를 사용해 확인할 필요가 없을 겁니다.따라서 deleteById 코드를 findByIddelete를 이용해 제가 직접 예외처리를 할 수 있는 코드로 수정했습니다.
다른 좋은 방법도 많겠지만 유동적으로 예외처리를 할 수 있다는 점에서 택했습니다.
코드는 아래와 같습니다.

public void deleteBoard(Integer boardId) throws Exception {
    Optional<Board> board = boardRepository.findById(boardId);

    if (board.isPresent()) {
      boardRepository.deleteById(board.get());
    } else {
      throw new Exception("Id Null Exception");
    }
  }
profile
공부 기록

0개의 댓글