1. View

uploadForm.mustache
                <h4 class="card-title">보유 스킬</h4>
                <table class="table">
                    <tr>
                        <td>
                            <div class=form-control style="display: flex; justify-content: space-evenly">
                                <input type="checkbox" name="skill" value="java">
                                <span>java</span>
                                <input type="checkbox" name="skill" value="javaScript">
                                <span>javaScript</span>
                                <input type="checkbox" name="skill" value="Spring">
                                <span>Spring</span>
                                <input type="checkbox" name="skill" value="HTML">
                                <span>HTML</span>
                                <input type="checkbox" name="skill" value="jQuery">
                                <span>jQuery</span>
                                <input type="checkbox" name="skill" value="MySQL">
                                <span>MySQL</span>
                                <input type="checkbox" name="skill" value="없음">
                                <span>없음</span>
                            </div>
                        </td>
                    </tr>2. 스킬 테이블
Skill
@Entity
@Data
@Table(name = "skill_tb")
public class Skill { // Tech Stack
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private Integer userId; // null 허용  -> 5
    private Integer employerId; // 1          -> null  채용공고로 옮김.
    private String skillName;
    private Integer boardId ; // 채용공고 id
    private Integer resumeId;
}
3. DTO
import java.util.List;
public class ResumeRequest {
    @Data
    public class UploadDTO {
        // title, cv, schoolName, major, educationLevel, career
        private String title;
        private String content;
        private String schoolName;
        private String major;
        private String educationLevel;
        private String career;
        private List<String> skill;
    }체크박스에서 name="skill" 으로 받은 데이터를 List 타입으로 받음.
4. 컨트롤러
SkillController
    @PostMapping("/resume/upload")
    public String upload(ResumeRequest.UploadDTO requestDTO) {
        User sessionUser = (User) session.getAttribute("sessionUser");
        Integer resumeId = resumeRepository.upload(requestDTO, sessionUser.getId());
        List<String> skills = requestDTO.getSkill();
        for (String skill : skills) {
            skillRepository.uploadByUserId(skill, sessionUser.getId(), resumeId);
        }
        return "redirect:/user/" + sessionUser.getId();
    }이력서를 작성하면서 기술 테이블에 데이터를 INSERT. 
skill 은 List 타입이기 때문에 반복문으로 하나씩 데이터를 추가한다.
5. 레파지토리
ResumeRepository
    @Transactional
    public Integer upload(ResumeRequest.UploadDTO requestDTO, Integer userId) {
        String q = """
                INSERT INTO resume_tb
                (user_id, title, content, school_name, major, education_level, career, created_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, now())
                """;
        Query query = entityManager.createNativeQuery(q);
        query.setParameter(1, userId);
        query.setParameter(2, requestDTO.getTitle());
        query.setParameter(3, requestDTO.getContent());
        query.setParameter(4, requestDTO.getSchoolName());
        query.setParameter(5, requestDTO.getMajor());
        query.setParameter(6, requestDTO.getEducationLevel());
        query.setParameter(7, requestDTO.getCareer());
        query.executeUpdate();
        String q1 = """
                select max(id) from resume_tb;
                """;
        Query query1 = entityManager.createNativeQuery(q1);
        Integer resumeId = (Integer) query1.getSingleResult();
      
        return resumeId ;
    }
이력서 INSERT.  Resume_tb 의 ID 조회를 위해 INSERT 후 MAX(ID) 를 조회한다.
SkillRepository
    @Transactional
    public void uploadByUserId(String skill, int userId,int resumeId) {
        String q = """
                INSERT INTO skill_tb(user_id, skill_name,resume_id) VALUES (?, ?,?)
                """;
        Query query = entityManager.createNativeQuery(q);
        query.setParameter(1,userId);
        query.setParameter(2,skill);
        query.setParameter(3,resumeId);
        query.executeUpdate();
    }

6. 데이터 출력
ResumeController
    @GetMapping("/resume/{resumeId}") //
    public String detail(@PathVariable int resumeId, HttpServletRequest request, Model model) { // ksj-030810 - model
        User sessionUser = (User) session.getAttribute("sessionUser");
        ResumeResponse.ResumeDetailDTO resumeDetailDTO = resumeRepository.detail(resumeId); // todo : resumeId가 없는 경우 처리
        resumeDetailDTO.isResumeOwner(sessionUser);
        request.setAttribute("resumeDetail", resumeDetailDTO);
        List<Skill> resumeSkillList = skillRepository.findByResumeId(resumeId);
        request.setAttribute("skillList", resumeSkillList);
  
        Double rawRating = ratingRepository.findBySubjectId(resumeDetailDTO.getUserId()); // ksj-030810
        if (rawRating != null) {
            // 소수점 한자리수까지 출력
            String rating = String.format("%.1f", rawRating);
            // model.addAttribute("resumeList", resumeDetailDTO.getId()); // ksj-03081
            model.addAttribute("rating", rating); // ksj-030810
        }
        if (sessionUser != null){
            Boolean hasRated = ratingRepository.hasRated(sessionUser.getId(), resumeDetailDTO.getUserId());
            request.setAttribute("hasRated", hasRated);
            Subscribe subscribe = subscribeRepository.findAllByUserIdResumeId(sessionUser.getId(), resumeId);
            request.setAttribute("subscribe", subscribe);
        }
        return "/resume/detail";
    }        List<Skill> resumeSkillList = skillRepository.findByResumeId(resumeId);
        request.setAttribute("skillList", resumeSkillList);
컨트롤러에서 이력서 ID를 이용해 데이터를 전달한다.
SkillRepositoty
    public List<Skill> findByResumeId(int resumeId) {
        String q = """
                select * from skill_tb where resume_id = ?
                """;
        Query query = entityManager.createNativeQuery(q,Skill.class);
        query.setParameter(1,resumeId);
        try {
            List<Skill> skillList = query.getResultList();
            return skillList;
        } catch (Exception e) {
            return null;
        }
    }resume/detail.mustache
                <h4 class="card-title">보유 스킬</h4>
                <div class="form-control mb-3">
                    {{#skillList}}
                        <btn class="btn btn-light">{{skillName}}</btn>
                    {{/skillList}}
                    {{^skillList}}
                        <btn class="btn btn-outline-light form-control">없음</btn>
                    {{/skillList}}
                </div>
Share article