JAVA & JSP & JavaScript
1일 ➜ 1440분
1/1440일 ➜ 1분
SYSDATE - createdAt < 1/1440
SYSDATE - createdAt < 10/1440
SYSDATE - createdAt < 1/24
SYSDATE - createdAt <1
selectList 메소드 수정// 원글(parentNum) 에 달린 모든 댓글을 리턴하는 메소드
public List<CommentDto> selectList(int parentNum){
List<CommentDto> list = new ArrayList<>();
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = new DbcpBean().getConn();
String sql = """
SELECT c.num, c.writer, c.targetWriter, c.content, c.deleted, c.groupNum,
u.profileImage,
CASE
WHEN SYSDATE - c.createdAt < 1/1440 THEN '1분 전'
WHEN SYSDATE - c.createdAt < 10/1440 THEN '10분 전'
WHEN SYSDATE - c.createdAt < 365 THEN
TO_CHAR(TRUNC(SYSDATE - c.createdAt)) || '일 전'
WHEN SYSDATE - c.createdAt < 730 THEN '1년 전'
ELSE '2년 이상'
END AS createdAt
FROM comments c
INNER JOIN users u ON c.writer = u.userName
WHERE c.parentNum = ?
ORDER BY c.groupNum ASC, c.num ASC
""";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, parentNum);
rs = pstmt.executeQuery();
while (rs.next()) {
CommentDto dto = new CommentDto();
dto.setNum(rs.getInt("num"));
dto.setWriter(rs.getString("writer"));
dto.setTargetWriter(rs.getString("targetWriter"));
dto.setContent(rs.getString("content"));
dto.setParentNum(parentNum);
dto.setGroupNum(rs.getInt("groupNum"));
dto.setDeleted(rs.getString("deleted"));
dto.setCreatedAt(rs.getString("createdAt"));
dto.setProfileImage(rs.getString("profileImage"));
list.add(dto);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
if (pstmt != null)
pstmt.close();
if (conn != null)
conn.close();
} catch (Exception e) {
}
}
return list;
}
// 대댓글의 갯수를 저장하기 위한 필드
private int replyCount;
public void setReplyCount(int replyCount) {
this.replyCount = replyCount;
}
public int getReplyCount() {
return replyCount;
}
selectList 메소드 수정public List<CommentDto> selectList(int parentNum){
List<CommentDto> list = new ArrayList<>();
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = new DbcpBean().getConn();
String sql = """
SELECT c.num, c.writer, c.targetWriter, c.content, c.deleted, c.groupNum,
u.profileImage,
CASE
WHEN SYSDATE - c.createdAt < 1/1440 THEN '1분 전'
WHEN SYSDATE - c.createdAt < 10/1440 THEN '10분 전'
WHEN SYSDATE - c.createdAt < 365 THEN
TO_CHAR(TRUNC(SYSDATE - c.createdAt)) || '일 전'
WHEN SYSDATE - c.createdAt < 730 THEN '1년 전'
ELSE '2년 이상'
END AS createdAt,
(SELECT COUNT(*)
FROM comments
WHERE groupNum = c.num AND num != groupNum) AS replyCount
FROM comments c
INNER JOIN users u ON c.writer = u.userName
WHERE c.parentNum = ?
ORDER BY c.groupNum ASC, c.num ASC
""";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, parentNum);
rs = pstmt.executeQuery();
while (rs.next()) {
CommentDto dto = new CommentDto();
dto.setNum(rs.getInt("num"));
dto.setWriter(rs.getString("writer"));
dto.setTargetWriter(rs.getString("targetWriter"));
dto.setContent(rs.getString("content"));
dto.setParentNum(parentNum);
dto.setGroupNum(rs.getInt("groupNum"));
dto.setDeleted(rs.getString("deleted"));
dto.setCreatedAt(rs.getString("createdAt"));
dto.setProfileImage(rs.getString("profileImage"));
dto.setReplyCount(rs.getInt("replyCount")); // 대댓글의 갯수
list.add(dto);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
if (pstmt != null)
pstmt.close();
if (conn != null)
conn.close();
} catch (Exception e) {
}
}
return list;
}
⭐ 스칼라 서브쿼리 이용
<%if(tmp.getReplyCount() != 0 && tmp.getNum() == tmp.getGroupNum()){ %>
<button class="dropdown-btn btn btn-outline-secondary btn-sm position-absolute"
style="bottom:16px; right:16px;">
<i class="bi bi-caret-down"></i>
답글 <%=tmp.getReplyCount() %> 개
</button>
<%} %>
<style>
/* 대댓글이 처음에는 보이지 않도록 하기 위해*/
.re-re{
display:none;
}
</style>
<div class="card mb-3 <%=tmp.getNum() == tmp.getGroupNum() ? "":"ms-5 re-re"%>">
document.querySelectorAll(".dropdown-btn").forEach(item => {
item.addEventListener("click", (e) => {
// click 이벤트가 발생한 그 버튼의 자손요소 중에서 caret up 또는 caret down 요소를 찾는다
const caret = item.querySelector(".bi-caret-up, .bi-caret-down");
// caret 모양을 위 아래로 토글 시킨다
if (caret) {
caret.classList.toggle("bi-caret-down");
caret.classList.toggle("bi-caret-up");
}
// 1. 버튼(item)의 두 단계 부모 요소로 이동
const grandParent = item.parentElement.parentElement;
// 2. 두 단계 부모 요소의 바로 다음 형제 요소의 참조값을 얻어낸다
let next = grandParent.nextElementSibling;
// 3. 반복문 돌면서 (다음 형제 요소가 있는 동안에 반복문 돌기)
while (next) {
// 만일 re-re 클래스가 존재한다면
if (next.classList.contains("re-re")) {
// d-block 클래스를 토글시켜서 보였다 숨겼다를 반복 시킨다
next.classList.toggle("d-block");
}else{ // 존재하지 않으면
// 반복문 탈출
break;
}
// 다음 형제 요소의 참조값 얻어내기
next = next.nextElementSibling;
}
});
});
⭐ 특정 요소의 기준으로 자식이나 부모, 형제 요소 등을 탐색하는 경우가 존재
in java
if(){
}
in javscript
if(){
}
➜ false , 0 , null , undefinded 는 값이 없다고 간주 된다
> if(true){ console.log("값이 존재");}
< 값이 존재
> if(false){ console.log("값이 존재");}
< undefined
> if(1){ console.log("값이 존재");}
< 값이 존재
> if(0){ console.log("값이 존재");}
< undefined
> if("kim"){ console.log("값이 존재");}
< 값이 존재
> if(null){ console.log("값이 존재");}
< undefined
> if(undefined){ console.log("값이 존재");}
< undefined
> if(NaN){ console.log("값이 존재");}
< undefined