Search
Duplicate

[스프링 게시판] 계층형 게시판

@3/23/2023

계층형 게시판 구현 방법

Oracle이라면 connect by, start with를 쓰면 된다고 하는데 MySQL은 힘들어보였다
Oracle 이외의 DB에서 계층형 게시판을 구현하는 여러가지 방법
재귀 쿼리 이용(복잡)
소수점 이용(복잡)
컬럼을 여러개 이용(다른 레코드 업데이트 필요)
함수 이용(복잡)
테이블이라는 리스트 구조를 트리 형태로 정렬하는 것이라 쉽지 않은 듯
나는 트리 구조를 표시하는 정렬용 컬럼을 만들어서 사용하기로 함
엑셀로 이런 식으로 생각해봤는데, 정렬이 쉽지 않아보임

NotNull 제약조건 문제

treePath는 id를 발급받아야만 넣을 수 있는데, 이렇게 하면 NotNull 조건에 위배돼서 insert 전에 가짜 값을 넣어줘야 하는 문제가 생김. 그래서 NotNull 제약조건은 없앰

Service 계층

데이터 추가 시
@Transactional public Long addPost(PostForm postForm, User writer, String parentTreePath) throws IOException { Post post = new Post(); post.setUser(writer); post.setTitle(postForm.getTitle()); post.setContent(postForm.getContent()); List<MultipartFile> multipartFiles = postForm.getUploadFiles(); if (multipartFiles != null) { List<UploadFile> uploadFiles = fileManager.storeFiles(multipartFiles); for (UploadFile uploadFile : uploadFiles) { uploadFile.addToPost(post); } } postRepository.save(post); // tree-path 지정 if (parentTreePath == null || parentTreePath.equals("")) { parentTreePath = "/"; } else { parentTreePath += "/"; } post.setTreePath(parentTreePath + post.getId()); String treePath = post.getTreePath(); String _root = treePath.split("/")[1]; post.setRoot(Long.parseLong(_root)); return post.getId(); }
Java
복사
조회 시 indentation
public List<PostListDTO> findAll(int pageNum, int pageSize, PostSearchDTO postSearchDTO) { int firstIndex = (pageNum - 1) * pageSize; List<PostListDTO> postListDTOs = postRepository.findAll(firstIndex, pageSize, postSearchDTO); // 날짜 포매팅 및 들여쓰기 처리 for (PostListDTO postListDTO : postListDTOs) { //날짜 포매팅 LocalDateTime regDate = postListDTO.getRegDate(); LocalDateTime now = LocalDateTime.now(); long diff = ChronoUnit.HOURS.between(regDate, now); if (diff < 24) { postListDTO.setFormattedRegDate(DateTimeFormatter.ofPattern("HH:mm").format(regDate)); } else { postListDTO.setFormattedRegDate(DateTimeFormatter.ofPattern("yyyy-MM-dd").format(regDate)); } //들여쓰기 long depth = postListDTO.getTreePath().chars().filter(c -> c == '/').count() - 1; StringBuilder newTitle = new StringBuilder(); if (depth >= 1) { for (int i = 0; i < depth; i++) { newTitle.append(" "); } newTitle.append("ㄴ "); newTitle.append(postListDTO.getTitle()); postListDTO.setTitle(newTitle.toString()); } } return postListDTOs; }
Java
복사
띄어쓰기가 먹히려면 글 제목이 들어가는 태그에 아래 CSS 설정을 해줘야 함
style="white-space: pre;"
Java
복사

결과화면

관련 커밋

bee90033336048621e7cdfa0171c3ef2c3ebac7f
commit

심각한 문제

예를 들어 id가 1인 글에 id가 2인 답글이 달리면 tree path가 /1/2가 됨
한참 후에 id가 1인 글에 아이디가 10인 답글이 달리면 tree path가 /1/10이 됨. 하지만 10이 2보다 숫자는 뒷순이지만 문자열은 앞순이기 때문에 순서가 뒤바뀜