10. Spring/실험

03. 스프링 부트 (Spring Boot 2) - JPA Test 시 유의사항 @Where

THE HEYDAZE 2021. 5. 30. 17:33
Board.class
@Data
@Table(name = "board")
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Board {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

//    @Filter(name = "cardsStatus", condition = "cards_status != del")
    @Where(clause = "status = 'success'")
    @OneToMany(mappedBy = "board")
    private List<Card> cards = new ArrayList<>();

    @Column
    private String name;

    public void addCard(Card card) {
        cards.add(card);
        card.setBoard(this);
    }
}

 

BoardRepository.class
public interface BoardRepository extends JpaRepository<Board, Long> {
}

 

Card.class
@Table(name = "card")
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
@ToString(exclude = "board")
public class Card {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JsonIgnore
    private Board board;

    @Column(name = "status")
    private String status;

    @Column(name = "name")
    private String name;
}

 

CardRepository.class
public interface CardRepository extends JpaRepository<Card, Long> {
}

 

Api.class
@Controller
@RequestMapping
@RequiredArgsConstructor
public class Api {

    private final BoardRepository boardRepository;

    private final CardRepository cardRepository;


    @PostMapping("/boards")
    @Transactional
    public ResponseEntity<?> saveBoard(@RequestBody BoardDto boardDto) {

        boardDto.getCards().forEach(cardId -> {
            Card card = cardRepository.findById(cardId).get();
            boardDto.getBoard().addCard(card);
        });

        Board save = boardRepository.save(boardDto.getBoard());
        System.out.println(save);
        return ResponseEntity.ok(save.toString());
    }

    @PostMapping("/cards")
    public ResponseEntity<?> saveCard(@RequestBody List<Card> card) {
        return ResponseEntity.ok(cardRepository.saveAll(card));
    }

    @GetMapping("/boards/{id}")
    public ResponseEntity<Board> findBoard(@PathVariable Long id) {
        return ResponseEntity.ok(boardRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("오류")));
    }

}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
class BoardDto {
    private Board board;
    private List<Long> cards;
}

 

BoardRepositoryTests.class
@DataJpaTest
class BoardRepositoryTests {

    @Autowired
    private EntityManager entityManager;

    @Autowired
    private BoardRepository boardRepository;

    @BeforeEach
    void setUp() {
        Board board = Board.builder()
                .name("something")
                .build();

        entityManager.persist(board);


        Card card1 = Card.builder()
                .name("card list1")
                .status("success")
                .board(board)
                .build();
        Card card2 = Card.builder()
                .name("card list2")
                .status("success")
                .board(board)
                .build();
        Card card3 = Card.builder()
                .name("card list3")
                .status("del")
                .board(board)
                .build();


        List<Card> cards = Arrays.asList(card1, card2, card3);

        entityManager.persist(card1);
        entityManager.persist(card2);
        entityManager.persist(card3);

        board.setCards(cards);

        entityManager.clear(); // << 이 부분 했을 때와 안했을 때 비교하시면 됩니다
    }

    @Test
    void findAll() {

        System.out.println(boardRepository.findById(1L));

//        boardRepository.findAll().forEach(System.out::println);

    }
}

 

PostMan 에서 조회할 때는 문제 없습니다 (save api 요청 시 이미 영속성 컨텍스트가 비워지기 때문임)

1

 

2
3

 

entityManager.clear() 를 사용하지 않는 경우, save 된 객체들이 영속성 컨텍스트 안에 존재하기 때문에
findAll() 테스트 코드를 실행 할 때 영속성 컨텍스트를 조회 한 뒤 있으면 DB 를 조회하지 않고 반환하여
Board @Entity 의 @Where 이 적용되지 않아 Board 의 cards 는 3개가 조회된다
때문에, @Where 이 적용되는지 확인하기 위해서는 영속성 컨텍스트를 비워주어야
'status=del' card는 제외가 되어 조회된다


 

clear 사용 전

 

clear 사용 후