개요
기존에 작업했던 ToDo API 에서 동적 쿼리 기능을 써보고자 해시태그 기능을 만들고 해시태그 기준으로 동적 쿼리로 검색하는 기능을 추가하려고 했다.
기존 ERD
수정 된 ERD
@Override
public CardResponseDto createTodoCard(CardPostRequestDto cardPostRequestDto, User user) {
String title = cardPostRequestDto.getTitle();
String content = cardPostRequestDto.getContent();
// 만약 글 내용이
// 오늘 할 일 1. 2. 3.
// #화이팅 #아아 #으으으으 뒤에 이런 글이 더 있다면
// hashTags[0] = 오늘 할 일 1. 2. 3.
// hashTags[1] = #화이팅
// hashTags[2] = #아아
// hashTags[3] = #으으으으 뒤에 이런 글이 더 있다면
// 인데?
// 이걸 한 번 더 나눠서
// 정규 표현식 사용?
// #[^\s#]+ 해시 태그 모두 포함
Card card = new Card(title, content, user);
cardRepository.save(card);
List<String> hashTagList = hashTagService.findHashTagByCardContent(card);
hashTagService.saveTag(hashTagList, card);
return new CardResponseDto(card);
}
주석에 많은 고민이 들어가 있다..
원래는 # 기준으로 Split을 할 생각이었는데, 여러가지 변수가 생길 수 있어서 정규 표현식을 사용하기로 했다!
여기 들어가면 작성한 정규표현식이 맞는지 확인이 가능하다
정규 표현식을 적용하려면 Pattern을 사용해야한다
글 내용에서 해시태그 뽑아내기
@Override
public List<String> findHashTagByCardContent(Card card) {
Pattern hasgTagPattern = Pattern.compile("#[^\\s#]+");
Matcher matcher = hasgTagPattern.matcher(card.getContent());
List<String> hashTagList = new ArrayList<>();
while (matcher.find()) {
hashTagList.add(matcher.group(0));
}
// 분리 하는 게 낫겠지?
// saveTag(hashTagList, card);
return hashTagList;
}
Pattern 을 적용하고 Pattern의 matcher 메서드를 이용해서 Matcher에다가 저장해준다
그리고 String을 담는 List를 만들어서 Matcher가 빌 때 까지 List에 해시태그들을 담아준다.
이러면 글 내용에 있는 해시태그들만 쏙쏙 골라서 List에 담아줄 수 있다.
해시태그 저장하기
@Override
public void saveTag(List<String> hashTagList, Card card) {
for (String name : hashTagList) {
// 저장 안 된 태그는 먼저 태그 테이블에 저장
if (!hashTagRepository.existsHashTagByName(name)) {
HashTag hashTag = builder().name(name).build();
hashTagRepository.save(hashTag);
}
// 이미 저장 된 태그라면 밑으로 빠지고
// 조인 테이블에 카드 및 태그 저장
HashTag hashTag = hashTagRepository.findHashTagByName(name);
CardHashTag cardHashTag = new CardHashTag(card, hashTag);
cardHashTagRepository.save(cardHashTag);
}
}
해시태그 별로 검색할 것이니 해시태그 레포지토리에 저장을 해준다.
만약 저장이 이미 된 해시태그면 저장하지 않는다.
그런 다음 해시태그와 글을 맵핑해주는 조인 테이블에도 저장한다.
글 수정 시에는 어떻게 할까?
글을 수정하면 해시태그 저장 된 것들을 어떻게 하나 고민을 많이 했다.
가장 간단한 방법을 떠올렸는데, 기존의 글 번호와 일치하는 것들을 글_해시태그 테이블에서 지운 뒤, 다시 해시태그 서치 -> 해시태그 저장을 반복하면 되겠다 생각했다.
Query Dsl로 만든 삭제 메소드
@Override
public void deleteTagMappingByCardId(Long cardId) {
queryFactory
.delete(cardHashTag)
.where(cardHashTag.card.id.eq(cardId))
.execute();
}
이 경우에는 조심해야할 것이 있다고 한다.
delete, update 등은 벌크연산이기 때문에 트랜잭션 환경을 무시하고 DB에 바로 쿼리를 날려서, 트랜잭션 환경이랑 DB 환경이랑 차이가 생길 수 있다.
private final JPAQueryFactory queryFactory;
private EntityManager em;
public 생성자() {
this.JPAQueryFactory = new JPAQueryFactory(em);
}
@Override
public void deleteTagMappingByCardId(Long cardId) {
queryFactory
.delete(cardHashTag)
.where(cardHashTag.card.id.eq(cardId))
.execute();
em.flush();
em.clear();
}
근데 이 메서드의 경우에는 이 이후에 트랜잭션을 활용하지 않고 종료돼서 굳이? 싶어서 안 넣었다.
나중에 추가해야할 이유가 생기면 추가할 예정이긴 하나, 아직쓰지는 않는 이유가
직접 트랜잭션이랑 DB 환경이 달라졌을 때 차이를 느껴보고, 경험하면 더 강하게 트랜잭션 환경을 초기화 해야하는 이유가 머릿속에 각인이 될 거 같아서 아직은 쓰지 않았다.
'TIL' 카테고리의 다른 글
TIL 2023-12-22 의존성에 대한... (0) | 2023.12.22 |
---|---|
TIL 2023-12-21 @Modifying QueryDsl에도 적용이 될까? (0) | 2023.12.21 |
TIL 2023-12-19 @WebMvcTest 와 Application JPAQueryFactory Bean 등록 오류 (2) | 2023.12.19 |
TIL 2023-12-18 QueryDSL Qclass 살펴보기... 삽질 (0) | 2023.12.18 |
TIL 2023-12-15 QueryDSL 기본 사용법 (0) | 2023.12.15 |