728x90

프로젝트를 진행하던 도중 Repository의 delete 메서드를 타이핑하고 있던 도중 자동 완성으로 두 가지 메서드가 내 눈앞에 등장했다.

해당 메서드들이 매개변수로 원하는 Integer id, Post entity가 둘 다 존재하는 상황이었다.

  1. 삭제해야 할 Post를 알아야하므로 Post Id를 매개변수로 넘겼기 때문에 Id가 존재했다.
  2. Post가 있어야 Post를 삭제할 수 있다는 조건을 해결하기 위해 Post Entity를 찾았기 때문에, Entity가 존재했다.

무엇을 선택해야 하는가 생각할 때, id만으로 비교하는 것보다 entity로 비교해서 삭제하는 게 좋지 않을까?라고 단순하게 생각하여 delete를 선택하고 엔티티를 넘겨 삭제 로직을 실행시켰다.

 

삭제 로직

@Service
@RequiredArgsConstructor
public class PostService {
    private final PostRepository postRepository;
    private final UserRepository userRepository;

    public void deletePost(Integer postId, String userName) {
        if (userName == null) {
            throw new SNSAppException(NOT_EXIST_TOKEN, NOT_EXIST_TOKEN.getMessage());
        }

        // user가 찾아지지 않는다면 삭제할 수 없다.
        User user = userRepository.findByUserName(userName)
                .orElseThrow(
                        () -> new SNSAppException(USERNAME_NOT_FOUND, USERNAME_NOT_FOUND.getMessage())
                );

        // post가 찾아지지 않는다면 삭제할 수 없다.
        Post post = postRepository.findById(postId)
                .orElseThrow(
                        () -> new SNSAppException(POST_NOT_FOUND, POST_NOT_FOUND.getMessage())
                );

        // User가 관리자가 아닌데, User와 Post를 작성한 User가 다르면 삭제할 수 없다.
        if (!user.getUserRole().equals(ADMIN) && !user.getId().equals(post.getUser().getId())) {
            throw new SNSAppException(INVALID_PERMISSION, INVALID_PERMISSION.getMessage());
        }

        // Post를 찾는 findById 메서드를 사용하였으므로 deleteById가 아닌 Delete 사용.
        postRepository.delete(post);
    }
}

이후 시간적 여유가 생겨 delete와 deleteById의 차이를 찾아보게 되었다.

 

Spring Data JPA 사용 시 deleteById 와 delete 의 차이

Spring Data 란? Spring Data’s mission is to provide a familiar and consistent, Spring-based programming model for data access while still retaining the special traits of the underlying data store. It makes it easy to use data access technologies, relati

hwanchang.tistory.com

 

SimpleJpaRepository의 delete

@Repository
@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
	...
	@Override
	@Transactional
	@SuppressWarnings("unchecked")
	public void delete(T entity) {

		Assert.notNull(entity, "Entity must not be null!");

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

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

		T existing = (T) em.find(type, entityInformation.getId(entity));

		// if the entity to be deleted doesn't exist, delete is a NOOP
		if (existing == null) {
			return;
		}

		em.remove(em.contains(entity) ? entity : em.merge(entity));
	}
}

Delete메서드를 보면 Entity Manager의 remove를 실행시키고 있는 것을 볼 수 있다.

 

SimpleJpaRepository의 deleteById

@Repository
@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
	...
	@Transactional
	@Override
	public void deleteById(ID id) {

		Assert.notNull(id, ID_MUST_NOT_BE_NULL);

		delete(findById(id).orElseThrow(() -> new EmptyResultDataAccessException(
				String.format("No %s entity with id %s exists!", entityInformation.getJavaType(), id), 1)));
	}
}

deleteById 메서드를 보면 먼저 findById 메서드를 실행시킨 후 해당 id의 데이터가 존재하면 delete를 진행하는 것을 볼 수 있다.

delete메서드 안에서 findById를 진행하여 원하는 예외를 발생시키는 것 또한 확인할 수 있었다.

 

 

결론

두가지 이유 때문에 나는 delete를 사용했다.

  1. 이미 내 로직 안에 findById로 Post를 찾았다
  2. 관리자인지, 작성자와 요청자가 동일한 인물인지 확인하는 조건 때문에 delete와 findById를 함께 사용할 수 없다.

만약에 두 가지 이유가 없었다면 내 delete메서드를 다음과 같이 수정하여 사용했을 것 같다.

@Service
@RequiredArgsConstructor
public class PostService {
    private final PostRepository postRepository;
    private final UserRepository userRepository;

    public void deletePost(Integer postId, String userName) {
        ...
        postRepository.delete(
                postRepository.findById(postId)
                        .orElseThrow(
                                () -> new SNSAppException(POST_NOT_FOUND, POST_NOT_FOUND.getMessage())
                        )
        );
    }
}
반응형

'Server > JPA' 카테고리의 다른 글

[JPA] Soft Delete를 위한 @SQLDelete, @Where  (0) 2023.01.06
[JPA] 01. JPA 시작  (0) 2022.09.15
[JPA] 00. JPA 소개  (0) 2022.09.14
코드플리