본문으로 바로가기

회원 가입 기능 만들기

category Spring boot 2024. 10. 10. 20:34

학습 목표 JPA를 활용하여 회원가입 기능을 구현할 수 있다.

 

 

package com.tenco.blog_v1.user;

import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@RequiredArgsConstructor
@Repository // IoC
public class UserRepository {

    private final EntityManager em;

    /**
     * 사용자 저장 메서드 (JPA API 사용)
     * @param user
     * @return 저장된 사용자 엔티티 
     */
    @Transactional
    public User save(User user) {
        // JPQL 은 INSERT 구문을 직접 지원하지 않습니다.
        em.persist(user); // 영속화
        return  user;
    }
    

    /**
     * 사용자 이름과 비밀번호로 사용자 조회
     * @param username
     * @param password
     * @return 조회된 User 엔티티, null
     */
    public User findByUsernameAndPassword(String username, String password) {
        TypedQuery<User> jpql =
                em.createQuery("SELECT u FROM User u WHERE u.username = :username AND u.password = :password", User.class);
        jpql.setParameter("username", username);
        jpql.setParameter("password", password);
        return jpql.getSingleResult();
    }

}

 

 

JPQL은 INSERT 문을 직접 지원하지 않습니다. 따라서 새로운 엔티티를 데이터베이스에 저장하려면 EntityManager의 persist 메서드를 사용해야 합니다. 만약 INSERT와 유사한 작업이 필요하다면 Native Query를 사용할 수 있습니다. 그러나 일반적인 경우에는 persist 메서드를 사용하는 것이 권장됩니다.

 

Native Query 사용 예시

@Transactional
public User saveV2(String username, String password, String email){
    Query q1 = em.createNativeQuery("insert into user_tb(username, password, email, created_at) values(?, ?, ?, now())");
    q1.setParameter(1, username);
    q1.setParameter(2, password);
    q1.setParameter(3, email);
    q1.executeUpdate();
    
    Query q2 = em.createNativeQuery("select * from user_tb where id = (select max(id) from user_tb)", User.class);
    User user = (User) q2.getSingleResult();
    return user;
}

 

 

JoinDTO 에 User 엔티티 변환 메서드 추가

package com.tenco.blog_v1.user;

import lombok.Data;

@Data
public class UserDTO {

    // 정적 내부 클래로 모우자
    @Data
    public static class LoginDTO {
        private String username;
        private String password;
    }

    // 정적 내부 클래로 모우자
    @Data
    public static class JoinDTO {
        private String username;
        private String password;
        private String email;

        public User toEntity() {
            return User.builder()
                    .username(username)
                    .password(password)
                    .email(email)
                    .build();
        }
    }
}

 

 

UserController 코드 추가

    @PostMapping("/join")
    public String join(@ModelAttribute(name = "joinDTO") UserDTO.JoinDTO reqDto)  {
        userRepository.save(reqDto.toEntity());
        return "redirect:/login-form";
    }

 

 

user/join-from.mustache

{{> layout/header}}

<main class="container p-5 content">
    <div class="card">
        <div class="card-header"><b>{{name}}</b></div>
        <div class="card-body">
            <form action="/join" method="post" enctype="application/x-www-form-urlencoded">
                <div class="mb-3">
                    <input type="text" class="form-control" placeholder="enter username" name="username">
                </div>

                <div class="mb-3">
                    <input type="password" class="form-control" placeholder="enter password" name="password">
                </div>

                <div class="mb-3">
                    <input type="email" class="form-control" placeholder="enter email" name="email">
                </div>

                <button type="submit" class="btn btn-primary form-control">회원가입</button>
            </form>

        </div>
    </div>

</main>

{{> layout/footer}}

 

 

UserRepository

    /**
     * 사용자 저장 메서드 (JPA API 사용)
     * @param user
     * @return 저장된 사용자 엔티티
     */
    @Transactional
    public User save(User user) {
        // JPQL 은 INSERT 구문을 직접 지원하지 않습니다.
        em.persist(user); // 영속화
        return  user;
    }

 

'Spring boot' 카테고리의 다른 글

@SessionAttribute 와 HttpSession을 멤버 필드로 주입 받는 것의 문제점  (0) 2024.10.18
회원 정보 수정  (0) 2024.10.10
게시글 수정 하기  (2) 2024.10.10
게시글 삭제  (0) 2024.10.08
게시글 쓰기  (0) 2024.10.08