Java/Spring

[SpringBoot/JPA] deleteById์— ์ž˜๋ชป๋œ ๊ฐ’์„ ๋„ฃ์–ด๋„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ

๋ฒผ๋ฆฌ01 2024. 3. 14. 14:53

๐Ÿ“Œํ™˜๊ฒฝ

IntelliJ Ultimate

Java 17

 

Spring boot 3.2.3

Gradle - Groovy

Dependencies: 

Spring Web

Thymeleaf

Spring Data JPA

lombok

MariaDB 10.11

Spring Dev tool

 

๐Ÿ“Œ๋ฌธ์ œ

`Reply`๋ฅผ ์‚ญ์ œ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•˜์—ฌ /URI/{rno}์— `DELETE` ๋ฐฉ์‹์œผ๋กœ ์‚ญ์ œ๋ฅผ ์š”์ฒญํ•จ.

`Reply`์˜ ์•„์ด๋””์ธ `rno`๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์กด์žฌํ•˜๋Š” ์•„์ด๋””๋กœ ์„ค์ •ํ•  ๊ฒฝ์šฐ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘. ๊ทธ๋Ÿฌ๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—†๋Š” ๋ฒˆํ˜ธ๋กœ ์„ค์ •ํ•˜๊ณ  ์š”์ฒญํ•˜๋ฉด Exception ์—†์ด code 200์„ ๋ฐ˜ํ™˜ ๋ฐ›์•˜์Œ.

๊ธฐ๋Œ€ํ–ˆ๋˜ Exception : `EmptyResultDataAccessException` 500

๊ฒฐ๊ณผ: 200

 

 

 

Hibernate: 
    select
        r1_0.rno,
        r1_0.board_bno,
        r1_0.moddate,
        r1_0.regdate,
        r1_0.reply_text,
        r1_0.replyer 
    from
        reply r1_0 
    where
        r1_0.rno=?

 

 

 

console์—์„œ select๋ฌธ๋งŒ ์‹คํ–‰๋˜๊ณ  ์•„๋ฌด๋Ÿฐ ์˜ค๋ฅ˜ ์—†์ด ๋๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค. ์‹ฌ์ง€์–ด `NoSuchElementException`๋„ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค... ๊ทธ๋ž˜์„œ `deleteById()` ๋ฉ”์„œ๋“œ๋ฅผ ๊นŒ๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.

 

`CrudRepository`์˜ ๊ตฌํ˜„์ฒด์ธ `SimpleJpaRepository`์˜ `deleteById()` ๋ฉ”์„œ๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

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

    Assert.notNull(id, ID_MUST_NOT_BE_NULL);

    findById(id).ifPresent(this::delete);
}

 

 

๋‚ด๋ถ€์—์„œ `findById()`๋ฅผ ์‹คํ–‰ํ•œ ํ›„ ์กด์žฌํ•˜๋ฉด `delete`๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ `findById(id)`๊ฐ€ null์ผ ๊ฒฝ์šฐ ์•„๋ฌด๋Ÿฐ Exception์„ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค!

 

2023๋…„ 1์›”์— ์ž‘์„ฑ๋œ ๋ธ”๋กœ๊ทธ์—์„œ ๋ดค๋˜ `deleteById`์™€ ๋‹ฌ๋ผ๋ณด์˜€๋‹ค. ์ถœ์ฒ˜: https://velog.io/@baekgom/deleteById-delete

 

https://velog.io/@baekgom/deleteById-delete

 

์ด๋ฏธ์ง€ ๋‚ด์—์„œ๋Š” `findById` ์‹คํ–‰ ์‹œ `orElseThrow( () -> new EmptyResultDataAccessException)`๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ณ  ์žˆ์œผ๋‚˜ ์ง์ ‘ ๊นŒ๋ณธ `SimpleJpaRepository`์—๋Š” ํ•ด๋‹น ๋‚ด์šฉ์ด ์—†์—ˆ๋‹ค. 

 

 

๊ทธ๋Ÿผ ์ด์ œ `delete()`๋ฅผ ๋ณด์ž.

 

@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) entityManager.find(type, entityInformation.getId(entity));

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

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

 

 

๋‚ด๋ถ€์—์„œ `entityManager`๊ฐ€ `find()`๋กœ ๊ฐ’์„ ์ฐพ์€ ๋’ค ์กด์žฌํ•  ๊ฒฝ์šฐ `remove()`๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‚ญ์ œํ•˜๊ณ  ์žˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ ์œ„์˜ ๋ธ”๋กœ๊ทธ์—์„œ ํ™•์ธํ•œ `delete()` ๋ฉ”์„œ๋“œ์™€ ๋™์ผํ–ˆ๋‹ค. 

๋ณ€๊ฒฝ๋œ ์ด์œ ๋Š” ์•Œ ์ˆ˜ ์—†์œผ๋‚˜ `deleteById()`์˜ ๋ฌธ์ œ๋กœ ๋ณด๊ณ  ์‚ญ์ œ ๋กœ์ง์„ ๋ณ€๊ฒฝํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

 

 

 

๐Ÿ“Œํ•ด๊ฒฐ

`Service`์—์„œ ์‚ญ์ œ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„ ์‹œ `deleteById()`๋ฅผ ์‚ฌ์šฉํ•จ์— ๋”ฐ๋ผ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋กœ ๋ณด๊ณ  `findById()`๋กœ ๊ฐ์ฒด๋ฅผ ์ฐพ์•„ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ `delete()`๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

 

@Override
public void remove(Long rno) {

//        replyRepository.deleteById(rno);

    Optional<Reply> result = replyRepository.findById(rno);
    Reply reply = result.orElseThrow();
    replyRepository.delete(reply);

}

 

 

 

 

`NoSuchElementException`์ด ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

๐Ÿ“Œ์ฐธ๊ณ 

์ž๋ฐ” ์›น ๊ฐœ๋ฐœ ์›Œํฌ๋ถ

https://velog.io/@baekgom/deleteById-delete

 

deleteById, delete

deleteById, delete

velog.io

https://docs.spring.io/spring-data/jpa/reference/repositories/core-domain-events.html#page-title

 

Publishing Events from Aggregate Roots :: Spring Data JPA

Entities managed by repositories are aggregate roots. In a Domain-Driven Design application, these aggregate roots usually publish domain events. Spring Data provides an annotation called @DomainEvents that you can use on a method of your aggregate root to

docs.spring.io