본문 바로가기

Spring boot/Blog 프로젝트 만들기(JPA)

완성 코드 STEP 02 - 회원 가입 ( JPA API , JPQL 쿼리 사용, 인증(세션 로직 추가 )

UserRepository
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-form.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;
    }
728x90