Spring & Spring Boot

스프링부트(Spring-Boot) - [ 회원관리 1편 ]

사과씨앗 2021. 1. 23. 14:00
728x90
반응형

안녕하세요 이번 글에서는 간단한 회원관리 기능을 만들어 보겠습니다.

 

( 인프런 김영한 강사님의 스프링부터 입문 강의를 학습한 내용입니다. )  www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8# 

 

프로젝트 구조는 이런 식으로 하겠습니다.

 

먼저 domain패키지 내부에 Member.class를 하나 만들어 주겠습니다.

package hello.hellospring.domain;

import javax.persistence.*;

@Entity //객체와 데이터베이스를 맵핑 해주기 위한 설정
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) //디비가 아이디를 자동으로 생성하여 주는 설정
    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

 

 

Controller 패키지 내부에 화면으로 정보를 받아올 MemberForm.class를 만들어 줍시다.

 

package hello.hellospring.controller;

public class MemberForm {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

 

그다음 controller패키지에 MemberController.class를 만들어 줍니다.

package hello.hellospring.controller;

import hello.hellospring.domain.Member;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.List;

@Controller
public class MemberController {

    private MemberService memberService;

    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }

    //회원가입 페이지로 이동시켜준다
    @GetMapping("/members/new")
    public String createForm(){
        return "members/createMembersForm";
    }

    //값을 저장하기 위해 POST 맵핑을 사용
    @PostMapping("/members/new")
    public String create(MemberForm form){
        Member member = new Member();
        //전달받은 form 에서 Name을 꺼내어 Member 객체에 셋팅
        member.setName(form.getName());
        memberService.join(member);
        //redirect 를 사용하여 처름화면으로 보내준다.
        return "redirect:/";
    }

    @GetMapping("/members")
    public String List(Model model){
        List<Member> members = memberService.findMembers();
        //회원 리스트를 보여주기 위해서 model 에 Member 리스트를 반환하여 준다.
        model.addAttribute("members",members);
        return "members/memberList";
    }


}

 

service패키지에 MemberService.class 만들어 줍니다.

 

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repogitory.MemberRepository;
import hello.hellospring.repogitory.MemoryMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
//@Transactional 선언하여 주면 트랜잭션을 단위를 선언한 부분에서 보장한다. Service 가 정삭적으로 끝나면 commit
@Transactional
public class MemberService {

    //Repository 를 Bean 에서 꺼내어 사용한다.
    private final MemberRepository memberRepository ;

    public MemberService(MemberRepository memberRepository){
        this.memberRepository = memberRepository;
    }

    /**
     * 회원가입
     */

    public Long join(Member member){
        //같은 이름의 중복 방지
        validateDuplicateMember(member);
        memberRepository.save(member);
        return member.getId();
    }
    //중복회원 검증
    private void validateDuplicateMember(Member member) {
        //ifPresent 사용시 값이 존재하면 내부함수가 실행된다
        memberRepository.findByName(member.getName())
                .ifPresent(m ->{
            throw new IllegalStateException("이미 존재하는 회원입니다.");
        });
    }
    /**
     * 전체회원조회
     */
    public List<Member> findMembers(){
        return memberRepository.findAll();
    }

    public Optional<Member> findOne(Long memberId){
        return memberRepository.findById(memberId);
    }

}

 

repository패키지에 MemberRepository.interface를 만들어줍시다.

 

package hello.hellospring.repogitory;

import hello.hellospring.domain.Member;

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

public interface MemberRepository {
    Member save(Member member);
    Optional<Member> findById(Long id);
    Optional<Member> findByName(String name);
    List<Member> findAll();
}

 

그다음 repository패키지에 MemberRepository를 사용할 구현체 클래스를 만들어 줍니다.

 

package hello.hellospring.repogitory;

import hello.hellospring.domain.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class JdbcTemplateMemberRepository implements MemberRepository{

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public JdbcTemplateMemberRepository(DataSource dataSource){
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override
    public Member save(Member member) {
        //SimpleJdbcInsert 사용하면 쿼리를 사용하지 않고 인설트할 수 있다.
        SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
        jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
        //Key 를 Id로 지정하여 자동으로 생성하게 해준다.

        Map<String, Object> parameters = new HashMap<>();
        parameters.put("name", member.getName());

        //직전에 인설트한 Member 의 Id를 가지고 온다.
        Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters));
        member.setId(key.longValue());
        return member;
    }

    //회원 아이디를 이용하여 찾기
    @Override
    public Optional<Member> findById(Long id) {
        List<Member> result = jdbcTemplate.query("select*from member where id = ?", memberRowMapper(),id);
        return result.stream().findAny();
    }
    //회원 이름을 이용하여 찾기
    @Override
    public Optional<Member> findByName(String name) {
        List<Member> result = jdbcTemplate.query("select*from member where name = ?", memberRowMapper(),name);
        return result.stream().findAny();
    }

    //전체회원 반환
    @Override
    public List<Member> findAll() {
        return jdbcTemplate.query("select*from member ", memberRowMapper());
    }

    //반환되어 오는 ResultSet(rs) 를 이용하여 Member 객체에 맵핑하여 준다.
    private RowMapper<Member> memberRowMapper(){
        return (rs, rowNum) -> {

            Member member = new Member();
            member.setId(rs.getLong("id"));
            member.setName(rs.getString("name"));
            return member;
        };
    }

}

 

마지막으로 SpringConfig에 다음과 같이 코드를 작성하여 줍시다.

package hello.hellospring;

import hello.hellospring.repogitory.*;
import hello.hellospring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class SpringConfig {


    //Repository 에서 사용할 dataSource 선언
    private DataSource dataSource;


    public SpringConfig( DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Bean
    public MemberRepository memberRepository(){
        return new JdbcTemplateMemberRepository(dataSource);
    }

    //빈으로 등록
    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }
}

 

글이 너무 길어져서

HTML화면과 디비 설정은 다음 글에서 이어서 하겠습니다 ^^

 

감사합니다

728x90
반응형