내 공고 업데이트 하기 기능

bethe·2022년 10월 14일
0

1. 공고관리 페이지로 이동하기 위해 href 주소에 값 두 개 받기

내 공고 목록보기 페이지에서 hover로 해당 공고의 공고관리 페이지와 지원자관리 페이지로 이동할 수 있도록 세팅되어 있었다.

[내 공고 목록보기 jsp파일 코드]

<div id="tab-1" class="notice_inner notice_inner1 tab-content on">
  <div class="notice_ul_wrap">
    <c:forEach var="noticeList" items="${noticeList}">
      <ul>
        <li>
          <a href="#"><img src="/img/logo_1.png" alt="logo" /></a>
        </li>
        <li>
          <a href="#">${noticeList.noticeTitle}
            <span class="notice_small">${noticeList.noticeTask}</span>
            <span class="notice_small">${noticeList.noticeDept}</span>
          </a>
        </li>
        <li>경력${noticeList.noticeCareer}<span class="notice_small">학력${noticeList.noticeQual}</span></li>
        <li>${noticeList.noticeWellfare}<span class="notice_small">커피무료</span></li>
        <li>${noticeList.noticePeriod}<span class="notice_small">마감 13일전</span></li>
      </ul>
    </c:forEach>
    <div class="notice_hover">
      <span><a
          href="/co/noticeService/${principal.companyId}/noticeDetail/${noticeList.noticeId}">공고관리</a></span>
      <span><a href="#">지원자관리</a></span>
    </div>
    <!-- .notice_hover -->
  </div>
</div>
<!-- .notice_inner1 -->

내 공고 목록보기 href가 /co/noticeService/{companyId}라 뒤에 noticeId를 붙여
<span><a href="/co/noticeService/${principal.companyId}/noticeDetail/${noticeList.noticeId}">공고관리</a></span> 라는 주소를 부여해주었다.

그런데

java.lang.NumberFormatException: For input string: "noticeId" 오류가 났다.

  • Entity에 타입이 잘못 되었는지 확인 👉 문제 없었음
  • href가 서로 다른 객체의 EL표현식 값을 다중으로 받지 못하는지 확인 👉 href를 걸지 않고 <li>태그 내부에서 서로 다른 객체(principal, noticeList)의 값이 코드 한 줄에 같이 출력되도록 해봄 👉 값이 무사히 받아짐
  • 파싱을 시도 👉 여전히 바인딩 에러 출력

💡 문제 원인
noticeList는 ArrayList 객체라 noticeId값 또한 하나가 아니었다.
👉 hover코드를 foreach문 안으로 옮겨 ArrayList출력이 되도록 해야 한다.

[수정 후 코드]

<c:forEach var="noticeList" items="${noticeList}">
  <ul>
    <li>
      <a href="#"><img src="/img/logo_1.png" alt="logo" /></a>
    </li>
    <li>
      <a href="#">${noticeList.noticeTitle}
        <span class="notice_small">${noticeList.noticeTask}</span>
        <span class="notice_small">${noticeList.noticeDept}</span>
      </a>
    </li>
    <li>경력${noticeList.noticeCareer}<span class="notice_small">학력${noticeList.noticeQual}</span></li>
    <li>${noticeList.noticeWellfare}<span class="notice_small">커피무료</span></li>
    <li>${noticeList.noticePeriod}<span class="notice_small">마감 13일전</span></li>
  </ul>
  <div class="notice_hover">
    <span><a
        href="/co/noticeService/${principal.companyId}/noticeDetail/${noticeList.noticeId}">공고관리</a></span>
    <span><a href="#">지원자관리</a></span>
  </div>
  <!-- .notice_hover -->
</c:forEach>

공고관리 버튼을 누르면 해당 noticeId 주소로 잘 이동된다.
문제는 hover버튼이 하나만 나오고 hover상태일 시 공고 영역이 검정색으로 변한다는 점인데, 프론트엔드를 담당한 팀원에게 물어보니 부모에게 position을 걸어주어야 한다고 들었다. 이 부분은 담당 팀원에게 맡기기로 하고 기능 구현을 진행하였다.


2. 공고관리 페이지 (공고 수정, 삭제 페이지)

2-1. Controller

[NoticeController.java]

초기 코드 :

@GetMapping("/co/noticeService/{companyId}/noticeDetail/{noticeId}")
    public String updateMyNotice(@PathVariable Integer companyId, Integer noticeId, Model model) {
        System.out.println("================");
        System.out.println("companyId : " + companyId);
        System.out.println("================");
        System.out.println("================");
        System.out.println("noticeId : " + noticeId);
        System.out.println("================");
        Notice noticePS = noticeService.내공고하나보기(noticeId);
        model.addAttribute("noticePS", noticePS);
        return "notice/noticeUpdate";
    }

🤔 발생한 문제
주소창의 noticeId값이 패러미터에 받아와지지 않고 null값으로 들어와 nullException이 발생했다.

❗️해결 방법
@PathVariable로 받는 값은 각 변수마다 @PathVariable 어노테이션을 붙여줘야 한다.

처음에는 하나가 아닌 두 개의 값을 받기 때문에 @PathVariable이 자동으로 값을 정확히 매핑해주지 못한다고 생각했다. 그래서 @Param을 붙여주었으나 여전히 Exception이 발생했다.

@Param으로 해결이 되지 않아 @PathVariable을 각 패러미터에 붙여주니 정상적으로 값을 받아왔다.

수정 후 코드 :

@GetMapping("co/noticeService/{companyId}/noticeDetail/{noticeId}")
    public String updateMyNotice(@PathVariable Integer companyId,
            @PathVariable Integer noticeId, Model model) {
        Notice noticePS = noticeService.내공고하나보기(noticeId);
        model.addAttribute("noticePS", noticePS);
        return "notice/noticeUpdate";
    }

✍️ @PathVariable과 @Param 구분하기

  • @PathVariable : URI에서 패러미터로 전달받은 value를 메서드의 패러미터로 받을 수 있게 해주는 어노테이션
  • @Param : DB에 다수의 변수를 전달할 때, 각 변수가 정확한 값에 매핑되도록 각 변수를 구분해주는 어노테이션

2-2. Service, Dao, Mapper

[NoticeService.java]

    public Notice 내공고하나보기(Integer noticeId) {
        return noticeDao.findById(noticeId);
    }

[NoticeDao.java]

public interface NoticeDao {
	public Notice findById(Integer noticeId);
}

[notice.xml]

	<select id="findById" resultType="site.metacoding.miniproject.domain.notice.Notice">
		SELECT *
		FROM notice
		WHERE notice_id = #{noticeId}
	</select>

2-3. jsp파일

1) model값 jsp에 출력하기

[noticeUpdate.jsp]

<div class="container">
      <div class="row">
        <div class="notice_update">
          <div id="notice_info" class="form">
            <div class="btn_group_delete">
              <div class="delete_btn">
                <button type="button" onclick="location.href='#'">공고삭제</button>
              </div>
            </div>
            <!-- delete_btn -->

            <div class="notice_form">
              <div class="notice_row">
                <div class="notice_list">
                  <p class="notice_list_item">공고명</p>
                </div>
                <div class="notice_input">
                  <input type="text" id="notice_title" name="notice_title" class="box_input"
                    value="${noticePS.noticeTitle}" placeholder="공고명을 입력하세요" />
                </div>
              </div>
              <div class="notice_row">
                <div class="notice_list">
                  <p class="notice_list_item">분야</p>
                </div>
                <div class="notice_input">
                  <div class="select-group">
                    <select>
                      <option>프론트엔드</option>
                      <option>백엔드</option>
                      <option>풀스택</option>
                      <option>안드로이드</option>
                      <option>IOS</option>
                    </select>
                  </div>
                </div>
              </div>
              <div class="notice_row">
                <div class="notice_list">
                  <p class="notice_list_item">공고마감일</p>
                </div>
                <div class="notice_input">
                  <input type="text" id="notice_period" name="notice_period" class="box_input"
                    value="${noticePS.noticePeriod}" placeholder="공고 마감일" />
                </div>
              </div>
              <div class="notice_row">
                <div class="notice_list">
                  <p class="notice_list_item">채용부서</p>
                </div>
                <div class="notice_input">
                  <input type="text" id="notice_dept" name="notice_dept" class="box_input"
                    value="${noticePS.noticeDept}" placeholder="부서명을 입력하세요" />
                </div>
              </div>
              <div class="notice_row">
                <div class="notice_list">
                  <p class="notice_list_item">채용직급</p>
                </div>
                <div class="notice_input">
                  <input type="text" id="notice_position" name="notice_position" class="box_input"
                    value="${noticePS.noticePosition}" placeholder="직급을 입력하세요" />
                </div>
              </div>
              <div class="notice_row">
                <div class="notice_list">
                  <p class="notice_list_item">주요업무</p>
                </div>
                <div class="notice_input">
                  <input type="text" id="notice_task" name="notice_task" class="box_input"
                    value="${noticePS.noticeTask}" placeholder="업무를 입력하세요" />
                </div>
              </div>
              <div class="notice_row">
                <div class="notice_list">
                  <p class="notice_list_item">평균연봉</p>
                </div>
                <div class="notice_input">
                  <input type="text" id="notice_sal" name="notice_sal" class="box_input" value="${noticePS.noticeSal}"
                    placeholder="연봉를 입력하세요" />
                </div>
              </div>
              <div class="notice_row">
                <div class="notice_list">
                  <p class="notice_list_item">자격요건</p>
                </div>
                <div class="notice_input">
                  <div class="form-check">
                    <input type="radio" class="form-check-input" id="radio1" name="optradio" value="option1" checked>대졸
                    <label class="form-check-label" for="radio1"></label>
                  </div>
                  <div class="form-check">
                    <input type="radio" class="form-check-input" id="radio2" name="optradio" value="option2">고졸
                    <label class="form-check-label" for="radio2"></label>
                  </div>
                </div>
              </div>
              <div class="notice_row">
                <div class="notice_list">
                  <p class="notice_list_item">경력기간</p>
                </div>
                <div class="notice_input">
                  <input type="text" id="notice_career" name="notice_career" class="box_input"
                    value="${noticePS.noticeCareer}" placeholder="경력 기간을 입력하세요" />
                </div>
              </div>
              <div class="notice_row">
                <div class="notice_list">
                  <p class="notice_list_item">복리후생</p>
                </div>
                <div class="notice_input">
                  <textarea id="company_wellfare" name="company_wellfare" cols="40" rows="5"
                    placeholder="복리 후생">${noticePS.noticeWellfare}</textarea>
                </div>
              </div>
            </div>
          </div>
          <!-- basic -->

          <div class="btn_group_update">
            <div class="update_btn">
              <button type="button" onclick="location.href='#'">수정완료</button>
            </div>
          </div>
          <!-- update_btn -->

        </div>
        <!-- notice_update -->
      </div>
    </div>
    <script src="/js/main.js"></script>
    <script src="/js/notice.js"></script>
    <%@ include file="../layout/footerCompany.jsp" %>

model값은 출력되었으나 분야<select>자격요건의 radio에
DB에 저장된 값이 선택된 상태로 출력되도록 해주어야 했다.

  • select-option 태그는 DB값을 불러오지 않아 맨 처음의 값이 선택되어 있고
  • radio 또한 DB값을 불러오지 않아 아무 것도 선택되어 있지 않은 상태다

2) 자격요건 DB값 불러와 radio 선택상태로 출력하기

💻 jstl c태그에서 사용하는 비교 연산자

  • eq : equal, 해당 값이 같은지 물어보는 연산자(==)
  • ne : not equal, 해당 값이 동일하지 않은지 물어보는 연산자(!= 또는 <>)

c태그 if문에 noticeQual이 해당 radio의 값이면 checked가 되도록 조건문을 걸어주었다.

  • if문을 걸어 noticeQual값이 '대졸'이면 checked
  • if문을 걸어 noticeQual값이 '고졸'이면 checked
<div class="form-check">
  <input type="radio" id="notice_qual" name="notice_qual" value="대졸" <c:if
    test="${'대졸' eq noticePS.noticeQual}">checked="checked"</c:if> /> 대졸
</div>
<div class="form-check">
  <input type="radio" id="notice_qual" name="notice_qual" value="고졸" <c:if
    test="${'고졸' eq noticePS.noticeQual}">checked="checked"</c:if> />고졸
</div>

단, value값을 위 코드처럼 직접 적어주어야 한다. 조건값에 value를 그대로 적으면 적용이 안 된다. test="${value eq noticePS.noticeQual}" 불가.


3) 분야 DB값 불러와 radio에 선택상태로 출력하기

우선 분야에 해당되는 job 테이블의 값을 model에 담아 foreach문으로 출력하도록 한다. 형식은 radio 형식으로 변환한다. 이 radio태그에 value값으로 jobCode값을 준다. (jobId로 설정되어 있는데 수정 필요)

[NoticeController.java]

    public String updateMyNotice(@PathVariable Integer companyId,
            @PathVariable Integer noticeId, Model model) {
        List<Job> jobPS = jobService.관심직무보기();
        model.addAttribute("jobPS", jobPS);
        Notice noticePS = noticeService.내공고하나보기(noticeId);
        model.addAttribute("noticePS", noticePS);
        return "notice/noticeUpdate";
    }

[jobService.java]

   public List<Job> 관심직무보기() {
   return jobDao.findAll();
    }

[noticeUpdate.jsp]

<c:forEach var="jobPS" items="${jobPS}">
  <input type='radio' id='job_id' name='job_id' value="${jobPS.jobId}" /> ${jobPS.jobName}
  <br>
</c:forEach>

자격요건과 마찬가지로 if문을 걸어준다.

<c:forEach var="jobPS" items="${jobPS}">
  <input type='radio' id='job_id' name='job_id' value="${jobPS.jobId}" <c:if
    test="${jobPS.jobId eq noticePS.jobId}">checked="checked"</c:if> /> ${jobPS.jobName}
  <br>
</c:forEach>


3. 내 공고수정 기능 구현

버튼이 클릭되면 ajax가 실행되도록 하기 위해 id를 부여한다.

<div class="update_btn">
  <button id="btnUpdateNotice" type="button">수정완료</button>
</div>

3-1. js코드 작성

1) 기초 코드 작성

[notice.js]

$("#btnUpdateNotice").click(() => {
  updateNotice();
});

function updateNotice() {
  let data = {
    noticeTitle: $("#notice_title").val(),
    jobId: $("#job_id").val(),
    noticePeriod: $("#notice_period").val(),
    noticeDept: $("#notice_dept").val(),
    noticePosition: $("#notice_position").val(),
    noticeTask: $("#notice_task").val(),
    noticeSal: $("#notice_sal").val(),
    noticeQual: $("#notice_qual").val(),
    noticeCareer: $("#notice_career").val(),
    noticeWellfare: $("#notice_wellfare").val()
  };

  $.ajax("/co/noticeUpdate/" + noticeId, {
    type: "PUT",
    dataType: "json",
    data: JSON.stringify(data), 
    headers: {
      "Content-Type": "application/json; charset=utf-8",
    }
  }).done((res) => {
    if (res.code == 1) {
      alert("내 공고 수정 완료");
      location.href = "/co/noticeService/" + companyId;
    } else {
      alert("내 공고 수정에 실패하였습니다");
    }
  });
}

2) noticeId, companyId를 받기 위해 jsp에 model값 받아오기

noticeId, companyId값을 받아오되 view에 출력되지 않으므로 type="hidden"으로 받아오기.

[noticeUpdate.jsp]

<input id="notice_id" type="hidden" value="${noticePS.noticeId}" />
<input id="company_id" type="hidden" value="${noticePS.companyId}" />

[notice.js]
function updateNotice()에

  let noticeId = $("#notice_id").val();
  let companyId = $("#company_id").val();

추가

주의할 점
//경로

location.href = "co/noticeService/" + companyId;

http://localhost:8000/co/noticeService/5/noticeDetail/co/noticeService/5


location.href = "/co/noticeService/" + companyId;

http://localhost:8000/co/noticeService/5
로 정상적으로 나옴


3) cehcked값, textarea값 받아오기

testarea 값 받기

noticeWellfare: $('textarea[name=company_wellfare]').val()

  let data = {
    companyId: $("#companyId").val(),
    noticeTitle: $('input[id=job_id]:checked').val(),
    noticeConame: $("#notice_period").val(),
    noticePeriod: $("#notice_dept").val(),
    noticeDept: $("#notice_position").val(),
    noticePosition: $("#notice_task").val(),
    noticeTask: $('input[id=noticeQual]:checked').val(),
    noticeSal: $("#notice_career").val(),
    noticeQual: $().val(),
    noticeCareer: $("#noticeCareer").val(),
    noticeWellfare: $("#noticeWellfare").val(),
    jobId: $('input[id=jobId]:checked').val()
  };

3-2. Controller, Service, Mapper

[NoticeController.java]

    @PutMapping("co/noticeUpdate/{noticeId}")
    public @ResponseBody CMRespDto<?> updateResume(@PathVariable Integer noticeId,
            @RequestBody NoticeUpdateDto noticeUpdateDto) {
        noticeService.이력서수정(noticeId, noticeUpdateDto);
        return new CMRespDto<>(1, "이력서 등록 성공", null);
    }

data가 noticeUpdateDto에 자동 매핑됨~ (내일쓰기)
noticeUpdateDto 코드는 아래에

[NoticeService.java]

    public void 이력서수정(Integer noticeId, NoticeUpdateDto noticeUpdateDto) {
        Notice noticePS = noticeDao.findById(noticeId); // 영속화
        noticePS.update(noticeUpdateDto);
        noticeDao.update(noticePS);
    }

[notice.xml]

	<select id="findById" resultType="site.metacoding.miniproject.domain.notice.Notice">
		SELECT *
		FROM notice
		WHERE notice_id = #{noticeId}
	</select>

3-3. Notice 엔티티에 update 메서드 생성

[NoticeUpdateDto.java]

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class NoticeUpdateDto {
    private String noticeTitle;
    private String noticePeriod;
    private String noticeDept;
    private String noticePosition;
    private String noticeTask;
    private String noticeSal;
    private String noticeQual;
    private String noticeCareer;
    private String noticeWellfare;
    private Integer jobId;
}

[Notice.java]

public void update(NoticeUpdateDto noticeUpdateDto) {
		this.noticeTitle = noticeUpdateDto.getNoticeTitle();
		this.noticeDept = noticeUpdateDto.getNoticeDept();
		this.noticePosition = noticeUpdateDto.getNoticePosition();
		this.noticeTask = noticeUpdateDto.getNoticeTask();
		this.noticeSal = noticeUpdateDto.getNoticeSal();
		this.noticeQual = noticeUpdateDto.getNoticeQual();
		this.noticeCareer = noticeUpdateDto.getNoticeCareer();
		this.noticeWellfare = noticeUpdateDto.getNoticeWellfare();
		this.jobId = noticeUpdateDto.getJobId();
	}

3-4. Notice 엔티티에 update 메서드 생성

[noticeDao.java]

public interface NoticeDao {
	public Notice findById(Integer noticeId);

	public void update(Notice notice);
}

[notice.xml]

	<update id="update">
		UPDATE notice SET
        notice_title = #{noticeTitle}, 
        notice_period = #{noticePeriod}, 
        notice_dept = #{noticeDept}, 
        notice_position = #{noticePosition}, 
        notice_task = #{noticeTask}, 
        notice_sal = #{noticeSal}, 
        notice_qual = #{noticeQual}, 
        notice_career = #{noticeCareer}, 
        notice_wellfare = #{noticeWellfare}, 
        job_id = #{jobId}
        WHERE notice_id = #{noticeId}
	</update>

노티스 Image insert에서 받을 것이므로 데이터베이스에서 빼고 entity수정해야 하지 않나
noticeConame도 필요없으면 없애도 될듯?

profile
코딩을 배우고 기록합니다. 읽는 사람이 이해하기 쉽게 쓰려고 합니다.

0개의 댓글