[Spring Boot] Mapper Interface 생성 + Mapper 작성하기

seulzzang·2023년 5월 29일
1

자바/Spring Boot

목록 보기
2/2
post-thumbnail


MyBtis라고 적은걸 오늘 알았다..


Mapper 인터페이스

  • Mapper인터페이스는 Mapping파일에 기재된 SQL을 호출하기 위한 인터페이스이다. 따라서 Mapping 파일에 있는 SQl을 자바 인터페이스를 통해 호출할 수 있도록 해준다.
  • 지난게시글에 작성했던 application.yml 에서 mybatis설정을 아래와같이 했었다.
mybatis:
  mapper-locations: classpath:mapper/**/*.xml
  configuration:
    map-underscore-to-camel-case: true
  type-aliases-package: com.project.devcenter.domain
  • Mapping파일의 위치를 resources안의 mapper폴더로 지정해주겠다~는 뜻이다.
    • mapper폴더 안의 xml확장자를 가진 애들을 다 mapper로 지정

1. Mapper Ineterface 생성

  • main-java 안에 mapper패키지를 생성해주고, 안에 인터페이스를 생성해준다.
package com.project.devcenter.mapper;

import com.project.devcenter.domain.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.Optional;

@Mapper
public interface UserMapper{

    Optional<User> findByEmail(String userEmail);

}
  • (제일 간단한거 가져왔음) @Mapper 어노테이션을 붙여줘야 mapper로 인식을 할 수 있음.

2. .xml에 쿼리 작성

  • resources-mapper에 Mapper.xml을 작성해준다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.project.devcenter.mapper.UserMapper">
	<select id="findByEmail" resultType="User">
	        SELECT
	        <include refid="userColumn"></include>
	        FROM tb_user
	        WHERE userEmail = #{username}
	</select>
</mapper>
  • mapper namespace에 내가 만든 Mapper이름과 동일하게 지정해주면 된다.
  • 이렇게 view에서 입력받는 username의 값으로 조건을 걸어주고 싶으면 #{username} 처럼 앞에 #을 붙여주면 된다.
    • 간단한 select는 위와같이 작성할 수 있다
<insert id="insertQuestion" parameterType="Question">
    INSERT INTO tb_question ( qUser
                            , qTitle
                            , qContent
                            , regDate)
    VALUES ( #{qUser}
           , #{qTitle}
           , #{qContent}
           , DATE_FORMAT(NOW(), '%Y%m%d%H%m%s'))
</insert>
  • insert, update, delete 등 역시 특정 값을 입력받는다 or 조건을 걸어주고싶다! 면 이와 같이.

여기까지 했다면 이제 데이터를 가져올 준비는 끝.

나는 mapper를 통해서 바로 controller에서 처리해주기 보단 service에서 과정을 거친 후에 controller model에 추가하는 편이다. (controller에서 바로 db에 접근하는건 지양한다고 한다)

3. Service

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;

		@Override
    public Optional<User> findByEmail(String userEmail) {
        return userMapper.findByEmail(userEmail);
    }
}
  • service 코드도 작성해주면 이제 controller에서 사용할 수 있다.

4. Controller

@GetMapping("myinfo")
public String myInfo(Model model) throws Exception {
    String userEmail = SecurityContextHolder.getContext().getAuthentication().getName();
    Optional<User> user = userService.findByEmail(userEmail);
    User member = user.orElseThrow(() -> new IllegalArgumentException("Invalid user Email: " + userEmail));
    Utils.decryptUserData(member);

    model.addAttribute("member", member);

    return "dev/dev_myinfo";
}
  • 위에서 Utils.decryptUserData(member); 는 신경쓸필요 없음. 개인정보 복호화를 위한 유틸함수기 때문에 model.addAttribute 만 보면 됨
  • model.addAttribute("member", member); 로 view에 넘겨줄 데이터를 model에 담아주기만 하면 된다.

5. View

  • tymeleaf를 사용한다면 view에서 이렇게 데이터를 불러올 수 있다.
  • jsp를 이용한다해도 똑같이 ${member} 의 형태로 데이터를 불러오면 됨.
<div class="w3-container">
    <!-- 메인 콘텐츠 영역 -->
    <table id="admin_service_table" class="w3-table w3-bordered w3-margin-bottom">
        <tr>
            <th>이름</th>
            <td th:text="${member.getUserRealName()}"></td>
        </tr>
        <tr>
            <th>가입일자</th>
            <td th:text="${#temporals.createDateTime(member.getRegDate(), 'yyyyMMddHHmmss')}"></td>
        </tr>
        <tr>
            <th>핸드폰 번호</th>
            <td th:text="${member.getUserPhoneNo()}"></td>
        </tr>
        <tr>
            <th>이메일</th>
            <td th:text="${member.getUsername()}" id="user_email"></td>
        </tr>
    </table>
    <button id="modify-user-pw" class="w3-button w3-white w3-border">비밀번호 변경</button>
    <button class="delete-user w3-button w3-red w3-border" type="button">계정 탈퇴</button>
</div>
  • get 을 안써도 되고 domain에 선언해둔 클래스의 객체값들을 바로 찍어도 됨. (member.regDate 이와 같이 써도 됨)

insert의 경우

<form action="/dev/question/apply" method="POST" id="question-form">
    <table id="question-table" class="w3-table w3-bordered w3-margin-bottom">
        <tr>
            <th>제목</th>
            <td><input type="text" name="qTitle" style="width:500px;" class="w3-input w3-border" required></td>
        </tr>
        <tr>
            <th>내용</th>
            <td><textarea name="qContent" style="width:500px; resize: none;" rows="10" cols="20" wrap="hard"
                          class="w3-input w3-border" required></textarea></td>
        </tr>
    </table>
</form>
  • view에서 name을 domain 클래스의 객체명과 동일하게 지정해준다.
  • form으로 controller에서 지정한 url로 POST요청을 보내면 된다.
@PostMapping( "question/apply")
public ResponseEntity<?> qApply(@ModelAttribute Question question) {
    /**
     * 문의 내역 POST
     */
    String userEmail = SecurityContextHolder.getContext().getAuthentication().getName();
    question.setQUser(userEmail);
    questionService.insertQuestion(question);

    return ResponseEntity.ok("등록이 완료되었습니다.");
}
  • @ModelAttribute : form에서 받은 데이터가 알아서 mapping
profile
중요한 것은 꺾이지 않는 마음

0개의 댓글