Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- multi module
- Item04
- db
- NotEmpty
- 플라이웨이트
- 데이터베이스
- @SpyBean
- Proxy Patter
- Firebase
- SQL 삽입 공격
- restTemplate
- deleteById
- 트랜잭션
- @Valid
- Effective Java
- Service Locator
- springboot
- Spring Boot
- @ControllerAdvice
- JPA
- Web
- Service Locator 패턴
- @MockBean
- FCM
- Effetive Java
- NotBlank
- java
- 디자인 패턴
- Connection Pool
- 이펙티브 자바
Archives
- Today
- Total
NoTimeForDawdling
[JPA] delete가 안되는 현상 본문
JpaRepository에서 delete() 메서드를 호출하여 삭제하려고 하는데 삭제가 안 되는 현상이 발생했다..!
코드는 에러없이 잘 돌아갔는데 자세히 보니 delete 쿼리가 실행되지 않았다!
소스 코드
Entity
@Entity
@Getter
@NoArgsConstructor(access = PROTECTED)
public class Product {
...
@OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true)
private List<InterestProduct> interestProductList = new ArrayList<>();
...
}
@Entity
@Getter
@NoArgsConstructor(access = PROTECTED)
public class InterestProduct {
...
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "product_id")
private Product product;
...
}
Delete Logic
...
@Transactional
public Long cancel(Long productId, Long interestedUserId) {
final Product product = productFindService.findProduct(productId);
final User interestedUser = userFindService.findUser(interestedUserId);
final InterestProduct interestProduct = interestProductRepository.findByProductAndInterestedUser(product, interestedUser)
.orElseThrow(() -> new IllegalArgumentException("not found interestProduct."));
interestProductRepository.delete(interestProduct);
return interestProduct.getId();
}
...
코드 설명
회원(User)이 관심 상품으로 등록한 상품(Product)이 맞다면 관심 상품(InterestProduct)을 찾고, 해당 관심 상품을 삭제하는 로직이다.
이 과정에서 JpaRepository의 delete() 메서드를 호출하였고, 코드는 에러 없이 잘 돌아갔다. 그런데 어째서인지 delete 쿼리가 실행되지 않았고, 실제 DB에도 삭제되지 않고 온전히 남아있었다.
해결 방법
상품(Product)를 같은 Transaction에서 검색한 후 관심 상품(InterestProduct)을 삭제할 경우 Product가 갖고 있는 InterestProduct도 같이 지워줘야 했다.
...
@Transactional
public Long cancel(Long productId, Long interestedUserId) {
final Product product = productFindService.findProduct(productId);
final User interestedUser = userFindService.findUser(interestedUserId);
final InterestProduct interestProduct = interestProductRepository.findByProductAndInterestedUser(product, interestedUser)
.orElseThrow(() -> new IllegalArgumentException("not found interestProduct."));
product.deleteInterestProduct(interestProduct); // Product가 갖고 있는 InterestProduct 삭제
interestProductRepository.delete(interestProduct);
return interestProduct.getId();
}
...
같은 Transaction이 아니면(해당 Transaction에 Product를 포함하지 않으면) InterestProduct가 잘 삭제되는 것도 확인할 수 있었다.
@Transactional
public Long cancel(Long interestProductId, Long interestedUserId) {
final InterestProduct interestProduct = findInterestProductById(interestProductId);
final User user = userFindService.findUser(interestedUserId);
if (interestProduct.isNotBelongToUser(user)) {
throw new IllegalArgumentException("user is not registered a interestProduct");
}
interestProductRepository.delete(interestProduct);
return interestProduct.getId();
}
한 transaction 안에서 서로 연관관계가 있는 두 Entity를 변경할 때 동기화를 꼭 해주자!
'JPA' 카테고리의 다른 글
[JPA] 쿼리 메서드(Query Method) (0) | 2021.08.27 |
---|---|
[JPA] Auditing 기능 (0) | 2021.07.31 |
[JPA] delete와 deleteById 차이 (0) | 2021.07.31 |