ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • mvc2( java, jsp, mybatis)
    LANGUAGE/Java, Spring 2024. 12. 2. 18:45

    - mvc2 순서

    더보기
    1. Controller 파일에서 url에 command 파라미터에 들어오는 값을 받아줌.
    2. 시작은 빈 값으로 들어오기 때문에 기본 ListAction / MainAction 등을 만듬.
    3. 페이지의 데이터를 생성, 수정, 삭제할 때마다 링크를 Controller의 servlet 링크로 연결해서 다른 Action으로 분기 시킴.
    4. Mapper는 xml 타입의 파일로 쿼리문을 사용해서 DBMS의 데이터를 조작.
    5. DAO는 Mapper에서 처리한 데이터를 Action으로 옮겨주는 역할.
    6. Action은 DAO의 메서드를 불러와서 가져온 데이터를 사용 목적에 맞게 조작.
    7. 이후 Action에서 req.setAttribute를 사용해 view에 위치한 jsp파일에 데이터를 뿌려줌.

     

    - Controller에서 get방식과 post방식을 동시에 처리하는 방법

    더보기
    // 서블릿을 정의하고 "/class.do" URL 패턴에 매핑합니다.
    @WebServlet("/class.do")
    public class ClassController extends HttpServlet {
    	// GET 및 POST 요청을 공통으로 처리하는 메서드입니다.
    		private void doProcess(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    			// 요청과 응답의 인코딩을 UTF-8로 설정합니다.
    			req.setCharacterEncoding("UTF-8");
    			resp.setContentType("text/html;charset=UTF-8");
    			
    			// cmd 파라미터를 가져옵니다.
    			String cmd = req.getParameter("cmd");
    			String url = "";
    			Action action = null;
    			
    			// cmd 파라미터 값에 따라 적절한 Action 객체를 생성.
    			if (cmd == null || cmd.equals("list")) {
    				action = new ListAction(); // cmd가 없거나 "list"인 경우, 리스트 액션을 수행.
    			} else if (cmd.equals("deleteClass")) {
    				action = new DeleteAction(); // class를 삭제. (delete가 아니라 update로 대체)
    			} else if (cmd.equals("addClass")) {
    				action = new InsertClassAction();  // class를 새로 생성.
    			} else if (cmd.equals("detailClass")) {
    				action = new DetailClassAction();  // class의 세부사항들을 보여줌. (class name, class teacher list, class kid list)
    			} else if (cmd.equals("classKidDelete")) {
    				action = new DeleteKidAction();  // class_kid 삭제 (업데이트)
    			} else if (cmd.equals("classTeacherDelete")) {
    				action = new DeleteTeacherAction();  // class_teacher 삭제 (업데이트)
    			} else if (cmd.equals("updateClassName")) {
    				action = new UpdateClassNameAction(); // class name 업데이트
    			} else if (cmd.equals("insertClassTeacher")) {
    				action = new InsertClassTeacherAction();  // class_teacer 생성
    			} else if (cmd.equals("insertKidTeacher")) {
    				action = new InsertClassKidAction(); // class_kid 생성
    			}
    			
    			// Action 객체의 execute 메서드를 호출하여 해당 작업을 수행하고, 결과 URL을 얻습니다.
    			url = action.execute(req, resp);
    			// 결과 URL로 포워딩합니다.
    			RequestDispatcher rd = req.getRequestDispatcher(url);
    			rd.forward(req, resp);
    		}
    		
    		
    	
    	// GET 요청을 처리합니다.
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		doProcess(req, resp);
    	}
    	
    	// POST 요청을 처리합니다.
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		doProcess(req, resp);
    	}
    	
    }



     

    - 조인과 서브쿼리 예시

    더보기
    <!-- 특정 클래스 번호를 통해 해당 클래스에 소속된 모든 선생의 이름과 ID를 조회하는 쿼리 -->
        <select id="selectAllTeacherByClass" parameterType="int" resultType="HashMap">
            SELECT mi.name, mi.id
            FROM class c
            JOIN class_teacher ct ON c.class_no = ct.class_no
            JOIN member_info mi ON ct.class_teacher_id = mi.id
            JOIN member m ON mi.id = m.id
            WHERE c.class_no = #{classNo}
            AND m.inactivate_date IS NULL
        </select>
        
        <!-- 특정 클래스 번호를 통해 해당 클래스에 소속되지 않은 모든 선생의 이름과 ID를 조회하는 쿼리 -->
        <select id="selectAllTeacherByClassNA" parameterType="int" resultType="HashMap">
            SELECT mi.name, mi.id
            FROM member_info mi
            WHERE mi.id NOT IN (
                SELECT ct.class_teacher_id
                FROM class_teacher ct
                JOIN class c ON ct.class_no = c.class_no
                WHERE c.class_no = #{classNo}
            )
        </select>
        
         <!-- 특정 클래스 번호를 통해 해당 클래스에 소속되지 않은 모든 원생의 이름과 번호를 조회하는 쿼리 -->
        <select id="selectAllKidByClassNA" parameterType="int" resultType="HashMap">
            SELECT k.kid_name, k.kid_no
            FROM kid k
            WHERE k.kid_no NOT IN (
                SELECT ck.kid_no
                FROM class_kid ck
                JOIN class c ON ck.class_no = c.class_no
                WHERE c.class_no = #{classNo}
            )
            AND k.discharge_date IS NULL;
        </select>

     

     

     

    - JSP파일에 Header와 Footer Include하기

    더보기
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>    
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Attendance Calendar</title>
    </head>
    <body>
        <div class="container mt-5 container-custom">
        	<!-- 헤더 파일 포함 -->
        	<jsp:include page="/include/header.jsp"></jsp:include>
        	
            <h1>월간 출석부</h1>
            <div id='calendar'></div>
            
            <!-- 푸터 파일 포함 -->
            <jsp:include page="/include/footer.jsp"></jsp:include>
        </div>
    </body>
    </html>

     

    - 출석부 페이지에 반 목록 띄우는 방법

    더보기
    1. main.jsp 페이지에 있는 달력에서 날짜 선택하면 해당 날짜(detail.jsp)로 이동
    2. detail.jsp에 class list를 dropdown 형식으로 보여주기 위해 dao에 selectAllClass 메서드 생성
    3. 해당 메서드에서 xml 형식의 mapper로 이동해서 select 쿼리문을 통해 class list 받아옴
    4. 다시 detail.jsp에서 req.setAttribute()를 통해 jsp 페이지에 class list 넘겨줌
    // DetailTodayAction.java
    public class DetailTodayAction implements Action {
    	@Override
    	public String execute(HttpServletRequest req, HttpServletResponse resp) {
    		// dao 만들어서 class 목록 가져와서 select-option에서 선택할 수 있도록 for문으로 뿌려줘야 됨 
    		AttendanceDAO adao = new AttendanceDAO();
    		List<HashMap<String, Object>> classList =  adao.selectAllClass();
    			
    		req.setAttribute("classList", classList);
    		return "views/admin/attendance/detailToday.jsp";
    	}
    }
    
    
    
    // AttendanceDAO.java
    public List<HashMap<String, Object>> selectAllClass() {
    		SqlSession ss = factory.openSession(true);
            List<HashMap<String, Object>> list =  ss.selectList("kr.co.aico.attendance.selectAllByClass");
            System.out.println("class list : " + list);
            ss.close();
            return list;
    }
    
    
    // attendance.xml
    <select id="selectAllByClass" resultType="HashMap">
            SELECT class_no, class_name, class_age, kinder_no, class_regdate, class_modify_date, class_delete_date  FROM class
    </select>

     

     

    - 테이블 두개 동시에 생성하기

    더보기
    1. 반에 해당하는 class_kid 또는 class_teacher를 생성하기 위해서는 그 전에 accept_log를 생성해야 됨.
    2. accept_log의 accept_no 컬럼을 받아서 class_kid의 accept_no에 대입. 
    3. accept_log의 accept_delete_date에 날짜를 입력할 경우 class_kid는 view쪽에서 안보이게 처리.
    4.  dao.java에서 메서드를 작성할 때 SqlSession타입의 변수를 factory.openSession(false)로 설정해서 자동 commit을 막음.
    5. 그리고 쿼리 문을 두 개 작성. (insertAcceptLog, insertKid)

     

    // ClassDAO.java
    // 특정 클래스 번호와 원생 번호로 새로운 원생 정보를 삽입하는 메서드
        public void insertKid(int classNo, int kidNo) {
            SqlSession ss = factory.openSession(false);
            
            HashMap<String, Object> params = new HashMap<String, Object>();
            params.put("classNo", classNo);
            params.put("kidNo", kidNo);
            
            // 수락 로그 삽입
            ss.insert("kr.co.aico.class.insertAcceptLog", params); 
            
            // 원생 정보 삽입
            ss.insert("kr.co.aico.class.insertKid", params); 
            
            ss.commit();
            ss.close();
        }
        
        
    // class.xml
    <!-- 새로운 수락 로그를 삽입하고 자동 증가된 accept_no 값을 반환하는 쿼리 -->
        <insert id="insertAcceptLog"
                keyProperty="accept_no"
                keyColumn="accept_no"
                useGeneratedKeys="true"
                parameterType="HashMap">
            INSERT INTO accept_log (accept_date, accept_status)
            VALUES (now(), 1)
        </insert>
    
    <!-- 새로운 원생 정보를 삽입하는 쿼리 (해당 원생이 이미 존재하지 않는 경우에만) -->
        <insert id="insertKid" parameterType="HashMap">
            INSERT INTO class_kid (class_no, kid_no, accept_no)
            SELECT #{classNo}, #{kidNo}, #{accept_no}
            WHERE NOT EXISTS (
                SELECT #{kidNo}
                FROM class_kid
                WHERE class_no = #{classNo} AND kid_no = #{kidNo}
            )
        </insert>

     

    - full calendar 라이브러리 사용 (jquery 사용해서 날짜 클릭시 해당 날짜로 이동)

    더보기
    $(document).ready(function() {
                var calendarEl = document.getElementById('calendar');
                var calendar = new FullCalendar.Calendar(calendarEl, {
                    initialView: 'dayGridMonth',
                    dateClick: function(info) {
                        // 현재 날짜를 가져옵니다.
                        var today = new Date();
                        // 클릭한 날짜를 가져옵니다.
                        var clickedDate = new Date(info.dateStr);
    
                        // 명령어를 저장할 변수를 초기화합니다.
                        var cmd = '';
    
                        // 클릭한 날짜와 현재 날짜를 비교합니다.
                        if (clickedDate.toDateString() === today.toDateString()) {
                            cmd = 'detailToday';
                        } else if (clickedDate < today) {
                            cmd = 'detailBefore';
                        } else {
                            cmd = 'detailAfter';
                        }
    
                        // window.location.href를 사용하여 적절한 URL로 이동합니다.
                        window.location.href = 'attendance.do?cmd=' + cmd + '&date=' + info.dateStr;
                    }
                });
                calendar.render();
            });

     

     

    - 출석부 설계

    더보기
    1. 시작 페이지인 main.js에는 full calendar 외부 라이브러리를 이용해서 월간 달력을 보여준다.
    2. 보고 싶은 출석부의 날짜를 선택
    3. 날짜가 오늘 이전이라면 이미 작성된 / 수정 불가능한 출석부 보여줌
    4. 날짜가 오늘 이후라면 출석부가 아직 작성되지 않았기 때문에 보여주지 않음
    5. 날짜가 오늘이라면 cmd=detailToday 컨트롤러에 보내지고 DetailTodayAction.java 생성
    6. jsp에서 action으로 가져오는 데이터들은 date, classNo 있고 session에서 kinderNo 불러옴
    7. dao selectOneByAttendanceDate() 1 이상이라면 출석부가 존재한다는 .
    8. 0이라면 '출석부 생성' 버튼이 화면에 뜨고
    9. 1이라면 출석부가 이미 존재하기 때문에 '수정' 버튼이 뜬다.
    10. 출석부 생성을 누르면 cmd=insertAttendance controller 넘어가고 AttendanceInsertAction 생성
    11. dao.selectAllByKinderNoAndClassNo 불러와서 출석부 테이블 insert

     

     

    만약 모달처럼 다른 페이지로 이동할 게 아니라면 jsp에서 controller -> action 방식으로 넘기지 말고 action 대신에 다른 servelet 파일 만들어서 값만 넣어도 됨



    'LANGUAGE > Java, Spring' 카테고리의 다른 글

    JSTL, EL 문법 정리  (1) 2024.12.03
    Java Enum  (0) 2024.12.03
    Java의 정석 정리 (06장)  (1) 2024.12.02
    Java의 정석 정리 (05장)  (2) 2024.12.02
    Java의 정석 정리 (04장)  (1) 2024.12.02
Designed by Tistory.