티스토리 뷰

- 사용 환경 

1) DBMS : MySQL (GUI 프로그램: DBeaver)

2) Framework : Spring boot + Thymeleaf + Bootstrap

3) IDE : Intellij

 

 

 

 


 

오늘의 과제
1. Database에 저장한 기안문 정보를 웹페이지에 출력하기   
    → 문제점 : JPQL 쿼리문 작성

2. Table을 클릭 시 기안문 세부 내용을 보여주도록 개발       
    → 문제점 : Javascript 외에 방법이 있는지 궁금

3. 세부 내용을 가독성있게 디자인하기                                   
    → 문제점 : Bootstrap 템플릿을 수정하지않고 수정해야함

 

1. Database에 저장한 기안문 정보를 웹페이지에 출력하기


1) DB에 저장된 기안문 정보

 

2) Spring boot에서 사용할 도메인 작성

   * 특이사항
   - MySQL의 datatype 중 timestamp를 이용하기 위해선 @Temporal(TemporalType.TIMESTAMP)를 이용
   - MySQL의 Auto increment를 사용할 경우 @GeneratedValue(strategy = GenerationType.IDENTITY)를 사용
     (MySQL의 기능 그대로 반영함.)

 

 

▣ Domain-Board 

    작성코드

 

더보기
package com.jun.DowooriVer2.domain;

import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.Date;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Data
@Table(name = "Board_table")
public class Board {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "Board_id")
    private Long id;

    private String title;
    private String empNum;
    private String deptNum;
    private String reason;

    @Temporal(TemporalType.TIMESTAMP)
    private Date startDate;

    @Temporal(TemporalType.TIMESTAMP)
    private Date endDate;

    @Temporal(TemporalType.TIMESTAMP)
    private Date writeDate;

    private String ampm;

    private String status;


}

 

 

 

▣ Repository - JpaBoardRepository

 * 문제점
   - 로그인시 받아온 empNum을 이용해 DB에 저장된 기안분 데이터를 가져오도록 JPQL 작성하는 과정에서 발생한 에러

Parameter value [1] did not match expected type [java.lang.String (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [1] did not match expected type [java.lang.String (n/a)]
org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [1] did not match expected type [java.lang.String (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [1] did not match expected type [java.lang.String (n/a)]

  - 에러 발생 이유
▶ 받아온 empNum파라미터의 데이터 타입은 Long
@Override public List<Board> findAll(Long empNum) {
TypedQuery<Board> queryResult = em.createQuery("select b from Board b where b.empNum = :number", Board.class).setParameter("number", empNum);

* 해결방법
▶ JPQL setParameter에 필요한 데이터 타입은 String
@Override public List<Board> findAll(Long empNum) {
TypedQuery<Board> queryResult = em.createQuery("select b from Board b where b.empNum = :number", Board.class) .setParameter("number", String.valueOf(empNum));  // Long -> String으로!!

 

 

    작성코드

 

더보기
package com.jun.DowooriVer2.repository;

import com.jun.DowooriVer2.domain.Board;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.util.List;

@Slf4j
@Repository
@RequiredArgsConstructor
public class JpaBoardRepository implements BoardRepository {

    private final EntityManager em;

    @Override
    public List<Board> findAll(Long empNum) {

        TypedQuery<Board> queryResult = em.createQuery("select b from Board b where b.empNum = :number", Board.class)
                .setParameter("number", String.valueOf(empNum)); // Long -> String으로!!

        List<Board> results = queryResult.getResultList();

        return results;
    }
}

 

 

3) model을 이용해 List<board> 객체를 home.html에 전달

 * 특이사항
   - model.addAttribute("객체이름", 객체)를 이용해 html로 전달

 

▣ Controller-HomeController

    작성코드

 

더보기
 @GetMapping("/home")
    public String homeLogin(HttpServletRequest request, Model model) {

        HttpSession session = request.getSession(false); //false : 새로 생성 X

        if(session == null){
            return "/";
        }

        Member loginMember = (Member) session.getAttribute(SessionConst.LOGIN_MEMBER);

        // 세션에 회원데이터가 없으면 로그인창으로
        if(loginMember == null){
            return "/";
        }

        log.info("loginMember.getEmpNum >> "+ loginMember.getEmpNum());

        Long empNum = loginMember.getEmpNum();

        List<Board> boards = boardService.findAll(empNum);


        model.addAttribute("boards", boards);
        model.addAttribute("member", loginMember);

        return "home";
    }

 

 

2) thymeleaf 문법 for-each를 이용해 boards=List<board>를 뽑아 출력

* 특이사항
    - th:block → 반복문을 사용할 구역을 정의할 때 사용
    - th:each="board : ${boards}" → boards에 담긴 객체를 반복문을 이용해 뽑아냄
    - th:text="${board.id}" → board에 담긴 id값을 text로 렌더링 후 웹페이지에 출력

 

▣ home.html

    작성코드

 

더보기
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
    <thead>
    <tr>
        <th>문서번호</th>
        <th>문서종류</th>
        <th>작성날짜</th>
        <th>결재현황</th>
    </tr>
    </thead>
    <tfoot>
    <tr>
        <th>문서번호</th>
        <th>문서종류</th>
        <th>작성날짜</th>
        <th>결재현황</th>
    </tr>
    </tfoot>
    <tbody>
        <th:block th:each="board : ${boards}">
            <tr>
                <td th:text="${board.id}">문서번호</td>
                <td th:text="${board.title}">문서종류</td>
                <td th:text="${board.writeDate}"> 작성날짜 </td>
                <td>
                	<span class="text btn btn-primary" th:text="${board.status}">결재현황</span>
                </td>
            </tr>
        </th:block>
    </tbody>
 </table>

 

 

 

 

2. Table을 클릭 시 기안문 세부 내용을 보여주도록 개발


* 문제점
   - Javascript를 이용하지 않고 table 클릭시 세부내용을 보여줄 수 있는 기능 개발

* 해결방법
   - Bootstrap에서 제공하는 accordion 기능 사용하여 구현

  1) 클릭시 기준이 될 tr태그(반복문 사용을 위해 board.id를 이용하여 해당 게시글 구분
    <tr data-toggle="collapse" th:attr="data-target='#accordion_'+${board.id}" class="clickable" >

  2) 클릭시 펼쳐질 td태그 (위에서 구분을 위한 board.id를 이용)
    <td colspan="4" class="collapse" th:id="'accordion_'+${board.id}">

 

 

▣ home.html

    작성코드

 

더보기
 <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
    <thead>
    <tr>
        <th>문서번호</th>
        <th>문서종류</th>
        <th>작성날짜</th>
        <th>더보기</th>
    </tr>
    </thead>
    <tfoot>
    <tr>
        <th>문서번호</th>
        <th>문서종류</th>
        <th>작성날짜</th>
        <th>진행상태</th>
    </tr>
    </tfoot>
    <tbody>
    <th:block th:each="board : ${boards}">
    <tr data-toggle="collapse" th:attr="data-target='#accordion_'+${board.id}" class="clickable" >
        <td th:text="${board.id}">문서번호</td>
        <td th:text="${board.title}">문서종류</td>
        <td th:text="${board.writeDate}"> 작성날짜 </td>
        <td>
            <span class="text btn btn-primary" th:text="${board.status}">
                결재현황
            </span>
        </td>
    </tr>
    <tr>
        <td colspan="4" class="collapse" th:id="'accordion_'+${board.id}">
 
            <div>
                <div>
                    <div>
                        <div>
                            <div>시작일</div>
                            <div th:text="${board.startDate}">시작일</div>
                        </div>
                        <div>
                            <div>종료일</div>
                            <div th:text="${board.endDate}">종료일</div>
                        </div>
                        <div>
                            <div>분류</div>
                            <div th:text="${board.ampm}">오전오후</div>
                        </div>
                        <div>
                            <div>사유</div>
                            <div th:text="${board.reason}">사유</div>
                        </div>
                	</div>
            	</div>  
            </div>
        </td>
    </tr>
    </th:block>
    </tbody>
</table>

 

 

 

 

 

3. 세부 내용을 가독성있게 디자인하기


* 문제점
   - Bootstrap template을 customizing에 어려움

* 해결방법
   <div style="display:flex">
      <div style="width:50%">구분할 태그1</div>
      <div style="width:50%">구분할 태그2</div>
   </div>

▶참고사항
Flex는 수평이 될 요소들의 Container(box-container)에 display: flex;를 적용
(세부 속성이 필요하지 않은 경우도 많기 때문에 상당히 쉽고 빠르게 수평 요소를 구성할 수 있습니다.)
- 출처 https://heropy.blog/2018/11/24/css-flexible-box/

 

 

▣ home.html

    작성코드

 

더보기
 <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
        <thead>
        <tr>
            <th>문서번호</th>
            <th>문서종류</th>
            <th>작성날짜</th>
            <th>더보기</th>
        </tr>
        </thead>
        <tfoot>
        <tr>
            <th>문서번호</th>
            <th>문서종류</th>
            <th>작성날짜</th>
            <th>진행상태</th>
        </tr>
        </tfoot>
        <tbody>
        <th:block th:each="board : ${boards}">
        <tr data-toggle="collapse" th:attr="data-target='#accordion_'+${board.id}" class="clickable" >
            <td th:text="${board.id}">문서번호</td>
            <td th:text="${board.title}">문서종류</td>
            <td th:text="${board.writeDate}"> 작성날짜 </td>
            <td>
                <span class="text btn btn-primary" th:text="${board.status}">
                    결재현황
                </span>
            </td>
        </tr>
        <tr>
            <td colspan="4" class="collapse" th:id="'accordion_'+${board.id}">
                    <!-- card example 1-->
                <div class="row">
                    <div class="col-xl-12 col-md-12 mb-4">
                        <div class="card border-left-primary shadow h-100 py-2">
                            <div class="card-body" style="display: flex;">
                                <div style="width: 50%;">
                                    <div class="row no-gutters align-items-center">
                                        <div class="col mr-2">
                                        <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">시작일</div>
                                        <div th:text="${board.startDate}" class="h5 mb-0 font-weight-bold text-gray-800">시작일</div>
                                        </div>
                                    </div>
                                    <div class="row no-gutters align-items-center">
                                        <div class="col mr-2">
                                        <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">종료일</div>
                                        <div th:text="${board.endDate}" class="h5 mb-0 font-weight-bold text-gray-800">종료일</div>
                                        </div>
                                    </div>
                                </div>
                                <div style="width: 50%;">
                                    <div class="row no-gutters align-items-center">
                                        <div class="col mr-2">
                                            <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">분류</div>
                                            <div th:text="${board.ampm}" class="h5 mb-0 font-weight-bold text-gray-800">오전오후</div>
                                        </div>
                                    </div>
                                    <div class="row no-gutters align-items-center">
                                        <div class="col mr-2">
                                            <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">사유</div>
                                            <div th:text="${board.reason}" class="h5 mb-0 font-weight-bold text-gray-800">사유</div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!-- card example 1-->
                </div>
            </td>
        </tr>
        </th:block>
        </tbody>
</table>

 

 


 

이상 개인프로젝트 사항 정리내용입니다.

긴 글 읽어주셔서 감사하고, 즐거운 연말연시 보내시길 바랍니다.!!!

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함