본문 바로가기
💻 뚝딱뚝딱/팀내도서대여시스템(OBRS)

[개발일지#002] 회원 가입 / 회원조회(단건) / 회원정보수정 구현

by 뚜루리 2024. 4. 1.
728x90
320x100
다른 사이드프로젝트인 '북북클럽'에서도 사용하는 거의 동일한 기능이라 이번에는 도메인 단위로 묶어서 개발일지를 써보기로 했다. 그래서, 이번 개발일지에는 '회원' 도메인에 관련된 기능을 구현할 예정. 

 

[개발목표]

  1. 회원 목록 조회 (#001에서 이미 구현했음)
  2. 회원 단건 조회 
  3. 회원 정보 수정
  4. 회원가입

 

 

UpdateForm.java

package seulgi.bookRentalSystem.domain.member;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.springframework.stereotype.Service;

@Setter @Getter
@RequiredArgsConstructor
public class UpdateForm {

    private String memberName;
    private String password;
}
  • 회원 수정용 객체를 따로 만들었다. 회원은 한번 가입하게 되면 멤버이름과 패스워드만 수정가능하기 때문에 두개의 엔티티만 담아주었다. 
  • 회원 수정시에 쓰게될 객체. 

 

 

MemberMapper.java

package seulgi.bookRentalSystem.domain.member;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Optional;

@Mapper
public interface MemberMapper {
	
    //회원 목록 조회
    List<Member> allMemberList();
	
    //로그인 기능을 위한 회원 조회
    Optional<Member> findByLoginId(@Param("loginId") String loginId);
	
    //회원 가입을 위한 조회
    void join(@Param("member") Member member);
	
    //회원Id을 통해 회원 객체 조회
    Member findById(@Param("memberId") String memberId);
	
    //회원 정보 수정 기능
    void update(@Param("memberId") String memberId, @Param("member") Member member);

}

 

 

MemberService.java

package seulgi.bookRentalSystem.domain.member;

import org.apache.ibatis.annotations.Param;
import seulgi.bookRentalSystem.domain.book.Book;
import seulgi.bookRentalSystem.domain.book.BookRental;

import java.util.List;

public interface MemberService {
	
    //회원 목록 조회
    List<Member> allMemberList();
    
	// 회원 가입 기능
    void join(Member member);
	
    //회원Id로 회원 객제 조회
    Member findById(String id);
	
    //회원 정보 수정
    void update(String memberId, UpdateForm updateForm);

}

 

 

MemberServiceImpl.java

package seulgi.bookRentalSystem.domain.member;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import seulgi.bookRentalSystem.domain.book.Book;
import seulgi.bookRentalSystem.domain.book.BookRental;

import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService{

    private final MemberMapper memberMapper;
	
    //회원 목록 조회
    public List<Member> allMemberList() {
        return memberMapper.allMemberList();
    }
	
    //회원 가입
    @Override
    public void join(Member member) {
        memberMapper.join(member);
    }
	
    //회원 아이디로 회원 객체 조회
    @Override
    public Member findById(String id) {
        return memberMapper.findById(id);
    }
	
    //회원 정보 수정
    @Override
    public void update(String memberId, UpdateForm updateParam) {
        Member findMember = findById(memberId);
        findMember.setMemberName(updateParam.getMemberName());
        findMember.setPassword(updateParam.getPassword());
        memberMapper.update(memberId, findMember);
    }


}
  • 회원수정 서비스에서 아까만든 회원수정용 객체를 사용하였다.

 

 

MemberMapper.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="seulgi.bookRentalSystem.domain.member.MemberMapper">
	
    <!-- 로그인용 회원 객체 조회 -->
    <select id="findByLoginId" parameterType="java.lang.String" resultType="seulgi.bookRentalSystem.domain.member.Member">
        SELECT
               MEMBER_ID AS mermberId
             , MEMBER_NAME AS memberName
             , PASSWORD
             , JOIN_DATE AS joinDate
            FROM MEMBER_TB WHERE MEMBER_ID = #{loginId}
    </select>
	
    <!-- 회원 단건 조회  -->
    <select id="findById" parameterType="java.lang.String"
                         resultType="seulgi.bookRentalSystem.domain.member.Member">
        SELECT
               MEMBER_ID AS memberId
             , MEMBER_NAME AS memberName
             , PASSWORD
             , JOIN_DATE AS joinDate
        FROM MEMBER_TB
        WHERE MEMBER_ID = #{memberId}
    </select>
    
	<!--회원 목록 조회 -->
    <select id="allMemberList" resultType="seulgi.bookRentalSystem.domain.member.Member">
        SELECT
              MEMBER_ID AS memberId
            , MEMBER_NAME AS memberName
            , PASSWORD
            , JOIN_DATE AS joinDate
        FROM MEMBER_TB;
    </select>
	
    <!-- 회원 가입 -->
    <insert id="join" parameterType="seulgi.bookRentalSystem.domain.member.Member">
        INSERT INTO MEMBER_TB
                ( MEMBER_ID
                , MEMBER_NAME
                , PASSWORD
                , JOIN_DATE
        ) VALUES (
                 #{member.memberId}
                ,#{member.memberName}
                ,#{member.password}
                ,now()
       )
    </insert>
	
    <!-- 회원 정보 수정 -->
    <update id="update" parameterType="java.util.Map">
        UPDATE MEMBER_TB
        SET   MEMBER_NAME = #{member.memberName}
            , PASSWORD = #{member.password}
        WHERE MEMBER_ID = #{memberId}
    </update>

</mapper>
  • Mybatis를 본격적으로 쓰는 것은 처음이라 현재 시간을 입력하기 위해 SYSDATE를 썼다가 에러가나서 보니 mybatis는 now()를 쓰더라. 아맞다..그랬지! 급하게 수정함. 
  • 전자정부프레임워크를 사용할 때는 egovMap을 쓰면 resultMap을 자동으로 카멜 형태로 변환해주기 때문에 그 편한 기능을 쓰다가 없으니 너무 불편하다. 일단 컬럼이 많지 않아 하나하나 alias를 적어서 변환해주고 있지만 찾아보니 변환하는 방법이 없는건 아닌거 같아 추후 수정을 해야 할 것 같다. 

 

MemberController.java

package seulgi.bookRentalSystem.web.member;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import seulgi.bookRentalSystem.domain.member.Member;
import seulgi.bookRentalSystem.domain.member.MemberServiceImpl;
import seulgi.bookRentalSystem.domain.member.UpdateForm;

import java.util.List;

@Controller
@RequiredArgsConstructor
@RequestMapping("/member")
public class MemberController {

    private final MemberServiceImpl memberService;

    /**
     * 회원가입 폼
     * @param model
     * @return
     */
    @GetMapping("/join")
    public String joinForm(Model model){
        model.addAttribute("member", new Member());
        return "member/joinForm";
    }

    /**
     * 회원가입
     * @param member
     * @param redirectAttributes
     * @return
     */
    @PostMapping("/join")
    public String join(@ModelAttribute Member member, RedirectAttributes redirectAttributes){
       memberService.join(member);
       redirectAttributes.addAttribute("memberId", member.getMemberId());
       redirectAttributes.addAttribute("status", true);
       return "redirect:/member/{memberId}";
    }

    /**
     * 회원 단건 조회
     * @param memberId
     * @param model
     * @return
     */
    @GetMapping("/{memberId}")
    public String member(@PathVariable String memberId, Model model){
        Member member = memberService.findById(memberId);
        model.addAttribute("member", member);
        return "member/member";
    }

    /**
     * 회원 목록 조회
     * @param model
     * @return
     */
    @GetMapping
    public String allMemberList(Model model){
        List<Member> members = memberService.allMemberList();
        model.addAttribute("members", members);
        return "member/allMemberList";
    }

    /**
     * 회원 정보 수정 폼
     * @param memberId
     * @param model
     * @return
     */
    @GetMapping("/{memberId}/edit")
    public String editForm(@PathVariable String memberId, Model model){
        Member member = memberService.findById(memberId);
        model.addAttribute("member", member);
        return "member/editForm";
    }
    /**
     * 회원 정보 수정
     * @param memberId
     * @param form
     * @return
     */
    @PostMapping("/{memberId}/edit")
    public String edit(@PathVariable String memberId, @ModelAttribute("member") UpdateForm form) {
        memberService.update(memberId, form);
        return "redirect:/member/{memberId}";
    }
}

 


[구현화면]

전에 했던 사이드프로젝트의 디쟌 그대로 가져온건 안비밀~ㅎ

728x90
320x100