50. PC를 이용한 데이터 삭제

박선규's avatar
Mar 14, 2024
50. PC를 이용한 데이터 삭제
 
notion image

게시글 삭제하기 JPQL

// 직접 조회 @Transactional public void deleteByIdV2(int id){ Board board = findById(id); em.remove(board); // PC에 객체 지우고, (트랜잭션 종료 시) 삭제 쿼리를 전송함 } // 쿼리문 직접 작성 @Transactional public void deleteById(int id){ Query query = em.createQuery("delete from Board b where b.id = :id"); query.executeUpdate(); }
📌
v2로 해도 되는데 repository에서 이 비즈니스로직을 짜게 되면 재사용이 불가능하며
원천적으로 srp가 안된다.
 
 
📌
  1. DELETE와 트랜잭션: remove() 메서드로 엔티티를 삭제하더라도, 트랜잭션이 커밋될 때까지 쿼리는 실행되지 않고, 트랜잭션 종료 시점에만 실제로 반영된다.
  1. 자식 트랜잭션: 부모 트랜잭션(외부 트랜잭션)이 우선 순위를 가지며, 자식 트랜잭션은 부모 트랜잭션에 의존적입니다. 부모 트랜잭션이 완료되기 전에는 자식 트랜잭션이 실행되지 않거나, 롤백되면 자식 트랜잭션도 롤백된다.
  1. 메타 어노테이션: 어노테이션 위에 적용된 또 다른 어노테이션을 의미하며, 어노테이션의 동작을 확장하거나 속성을 정의하는 역할을 한다.
public void deleteByIdV2(int id) { em.getTransaction().begin(); try { Board board = findById(id); em.remove(board); } catch (Exception e) { em.getTransaction().rollback(); } em.getTransaction().commit(); }
이 코드가 @Transactional 의 역할이다.
💡
만약 remove를 때린 상태에서 트랜잭션이 종료하기 전에 다시 조회를 하면 그 결과가 다시 db에서 조회를 해서 가져오기 때문에 삭제가 안된 것으로 착각 할 수 있다.
 

단위 테스트

버전1
@Test public void deleteByIdV1_test(){ int id = 1; boardReposiroty.deleteById(id); }
 
notion image
 
📌
버전1을 사용하면 정상적으로 delete 쿼리가 전송된다.
 

버전2

@Test public void deleteByIdV2_test(){ int id = 1; boardReposiroty.deleteByIdV2(id); }
 
notion image
 
버전2를 사용하면 select 쿼리만 발동되고 delete 쿼리는 발동되지 않는다.
 
📌
트랜잭션 내부에 있는 쿼리는 트랜잭션이 완료된 이후에 PC에서 DB 로 쿼리가 전송된다. 하지만 JUnit 테스트에서는
@Test내부에도 트랜잭션이 있기 때문에 이중 트랜잭션이 된다. 따라서 delete 메서드 내부의 트랜잭션이 종료되더라도, JUnit 내부의 트랜잭션이 종료되지 않고, JUnit이 종료되면 프로그램 실행이 종료되기 때문에 따로 쿼리가 전달되지 않는다.
 
notion image
 
💡
단위 테스트를 할 때 쿼리문이 보이지 않아서 테스트가 힘들기 때문에 강제로 쿼리를 날려버리면 된다!!
@Test public void deleteByIdV2_Test(){ // given int id = 1; // when boardPersistRepository.deleteByIdV2(id); // 버퍼에 쥐고 있는 쿼리를 즉시 전송 em.flush(); // 강제로 쿼리 쏘기 em.clear(); // Persistent Context 전체를 비워버리는 기능 // then }
notion image
 

컨트롤러

@PostMapping("/board/{id}/delete") public String delete(@PathVariable Integer id){ boardPersistRepository.deleteById(id); return "redirect:/"; }
 
notion image
notion image
 
 
 
 
 
Share article

p4rksk