@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
복사
결과화면
관련 커밋
심각한 문제
•
예를 들어 id가 1인 글에 id가 2인 답글이 달리면 tree path가 /1/2가 됨
•
한참 후에 id가 1인 글에 아이디가 10인 답글이 달리면 tree path가 /1/10이 됨. 하지만 10이 2보다 숫자는 뒷순이지만 문자열은 앞순이기 때문에 순서가 뒤바뀜