1.user 패키지

- User 패키지에 UserController, UserRepository, UserReuest 클래스 파일 만들기
2. User
package shop.mtcoding.blog.user;
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import java.sql.Timestamp;
@Getter
@Setter
@Table(name= "user_tb")
@NoArgsConstructor
@Entity
public class User {
//비정형 데이터는
//N쪽에 포린키 가 있어야 한다.
//명사들 생각하다가 둘의 관계를 보다가 동사,명사가 된다.
//N:N 이면 무조건 중간에 동사가 나온다.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(unique = true , nullable = false)
private String username; // 아이디
@Column(nullable = false)
private String password;
@Column(nullable = false)
private String email;
@CreationTimestamp // 하이버네이트의 도움을 받으면 자동으로 시간이 등록된다.
private Timestamp createdAt;
@Builder
public User(Integer id, String username, String password, String email, Timestamp createdAt) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
this.createdAt = createdAt;
}
@CreationTimestamp // 하이버네이트의 도움을 받으면 자동으로 시간이 등록된다.
private Timestamp createdAt;
3. UserController
1. 회원가입
package shop.mtcoding.blog.user;
import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class UserController {
private final UserRepository userRepository;
private final HttpSession session;
public UserController(UserRepository userRepository, HttpSession session) {
this.userRepository = userRepository;
this.session = session;
}
//회원가입 하고 난 후
@PostMapping("/join")
public String join(UserRequest.joinDTO joinDTO) {
//insert 하는 모든 것들은 toEntitiy로 하면 된다.
userRepository.save(joinDTO.toEntity());
return "redirect:/login-form";
}
- ‘UserRequest.joinDTO’ 는 메소드의 매개변수인 ‘joinDTO’는 사용자가 폼에서 입력한 데이터를 담고 있는 객체이다. DTO(Data Transfer Object)는 데이터를 전송을 위한 객체로, 주로 요청이나 응답 시 데이터 구조를 정의하는데 사용한다.
- ‘joinDTO.toEntitiy()’ 는 ‘joinDTO’ 객체를 ‘User’ 엔티티 객체로 변환하고 ‘toEntity()’ 메소드는 DTO를 엔티티로 변환하는 역할을 한다. 엔티티는 데이터베이스 테이블과 매핑된 객체로 ‘joinDTO’에 담긴 데이터를 ‘User’엔티티로 변화하여 데이터베이스에 저장이 가능하다.
- ‘userRepository.save()’ 이 부분에서 변환된 ‘User’ 엔티티 객체를 데이터베이스에 저장한다.
2.로그인
@PostMapping("/login")
public String login(UserRequest.loginDTO loginDTO) {
User sessionUser = userRepository.findByUsernameAndPassword(loginDTO.getUsername(),loginDTO.getPassword());
session.setAttribute("sessionUser", sessionUser);
return "redirect:/board";
}
- ‘UserRequest.loginDTO’ 매개변수는 사용자가 로그인 폼에서 입력한 데이터를 담고 있는 객체이다.
- ‘userRepository.findByUsernameAndPassword(..): 데이터베이스에서 사용자 정보를 조회하는 메소드 호출이다. 데이터베이스에서 ‘username’, ’password’가 모두 일치하는 사용자를 검색한다. 만약 일치하는 사용자가 있다면 해당 ‘User’ 엔티티가 반환되고 그렇지 않으면 ‘null’이 반환된다.
- ‘sessionUser’는 데이터베이스에서 조회된 사용자 객체를 나타내고있다. 로그인 정보가 맞다면 ‘sessionUser’에는 사용자의 정보가 담긴 ‘User’객체를 저장한다.
- ‘session.setAttribute(…): 이 코드는 현재 사용자의 세션에 데이터를 저장한다.
3.UserRepository
1. 회원정보 조회
package shop.mtcoding.blog.user;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.sql.Timestamp;
import java.time.LocalDateTime;
@Repository
public class UserRepository {
@Autowired
private EntityManager em;
public User findByUsernameAndPassword(String username, String password) {
Query query = em.createQuery("select u from User u where u.username=:username and u.password=:password", User.class);
query.setParameter("username", username);
query.setParameter("password", password);
User user = (User) query.getSingleResult();
return user;
}
- ‘public User findByUsernameAndPassword(String username, String password) 는 주어진 ‘username’과 ‘password’ 에 해당하는 사용자를 데이터베이스에서 찾아 반환한다. ‘User’ 메서드는 ‘User’ 엔티티 객체를 반환한다. 사용자를 찾지 못 하면 예외가 발생한다.
- Query query = em.createQuery(): ‘EntityManger’의 메소드로 , JPQL 쿼리를 생성한다. JPQL은 엔티티 객체를 대상으로 하는 쿼리 언어다. 엔티티 객체를 기반으로 작동한다.
- "select u from User u where u.username=:username and u.password=:password", User.class는 JPQL쿼리이다. ‘u’는 ‘User’ 엔티티의 별칭이다. User.classs는 쿼리결과를 ‘User’ 타입으로 매핑하기 위한 정보다.
- User user = (User) query.getSingleResult(); 쿼리를 실행하여 정확히 하나의 결과를 반환한다. 쿼리 실행 결과로 반환된 ‘User’객체를 ‘user’변수에 저장합니다 이 메서드는 쿼리의 결과가 없거나 여러 개의 결과가 반환될 경우 예외를 발생시킵니다.
- 예외:
javax.persistence.NoResultException
(결과가 없을 때)
- 예외:
javax.persistence.NonUniqueResultException
(여러 결과가 있을 때)
2. 회원가입 수행
@Transactional // 비영속 객체를 영속성 컨텍스트에 잠깐 스치면 바로 insert 해준다.
public void save(User user) {
System.out.println("담기기전 :" + user.getId());
em.persist(user);
System.out.println("담기기후 :" + user.getId());
}
영속성 컨텍스트(Persistence Context)는 JPA(Java Persistence API)에서 중요한 개념으로, 애플리케이션과 데이터베이스 사이의 데이터 상태를 관리하는 메커니즘입니다. JPA는 객체와 데이터베이스 간의 매핑을 처리하며, 영속성 컨텍스트는 이 과정에서 객체의 상태를 관리합니다.
영속성 컨텍스트 요약
- 개념:
- 영속성 컨텍스트는 엔티티(Entity) 객체들을 관리하는 일종의 "저장소"입니다.
- 엔티티 객체들이 영속성 컨텍스트에 포함되면 "영속 상태"가 됩니다.
- 영속성 컨텍스트는 엔티티의 생명 주기를 관리하고, 데이터베이스와의 동기화를 담당합니다.
- 상태 관리:
- 비영속 (Transient): 영속성 컨텍스트와 관계없는 상태로, 데이터베이스에 저장되지 않은 상태입니다.
- 영속 (Persistent): 영속성 컨텍스트에 의해 관리되는 상태로, 데이터베이스에 저장되거나 저장될 수 있는 상태입니다.
- 준영속 (Detached): 한때 영속 상태였지만, 현재는 영속성 컨텍스트에 의해 관리되지 않는 상태입니다.
- 삭제 (Removed): 삭제될 예정인 상태로, 영속성 컨텍스트에 의해 관리되지만, 트랜잭션이 커밋되면 데이터베이스에서 삭제됩니다.
요약
영속성 컨텍스트는 엔티티 객체를 관리하고, 데이터베이스와의 동기화 작업을 수행하는 JPA의 핵심 개념입니다. 이 컨텍스트는 엔티티의 상태를 관리하고, 성능 최적화, 상태 변경 감지, 동일성 보장 등을 통해 데이터 일관성을 유지합니다.
- 비영속 상태의 ‘User’ 객체가 메소드의 매개변수로 전달된다.
- ‘em.persist(user)’ 를 호출하여 ‘User’ 객체를 영속성 컨텍스트에 포함시킨다. 이 시점에서 객체의 ‘id’가 설정될 수 있고, 트랜잭션이 커밋될 때 ‘INSERT’ 쿼리가 데이터베이스에서 실행된다.
- 이 메소드는 비영속 상태의 ‘User’ 객체를 영속 상태로 전환하여, 데이터베이스에 저장하는 작업을 수행합니다
- ‘persist'메서드를 통해 영속성 컨텍스트에 포함된 객체는 이후 데이터베이스에 저장됩니다.
4. UserRequest(DTO)
package shop.mtcoding.blog.user;
import lombok.Data;
public class UserRequest {
@Data
public static class joinDTO{
private String username;
private String password;
private String email;
//DTO를 -> UserObject로 바꿔준다.
public User toEntity(){
return User.builder().username(username).password(password).email(email).build();
}
}
@Data
public static class loginDTO{
private String username;
private String password;
}
- ‘joinDTO’ 클래스는 사용자의 회원가입 요청에서 사용될 데이터를 담는 역할을 합니다.
- ‘public User toEntity()’는 ‘joinDTO 객체를 ‘User’엔티티로 변환합니다. 회원가입 폼에서 입력된 데이터를 데이터베이스에 저장하기 위해 ‘User’ 객체로 변환하는 것이 필요하기 때문에 이 메소드가 사용됩니다.
- ‘User.builder()’: ‘User’ 엔티티를 생성하는 빌더 패턴을 사용한다. 이 패턴은 객체 생성과 유연성과 가독성을 높이기 위해 사용된다. ‘build()’ 설정된 필드를 기반으로 ‘User’객체를 생성하고 반환합니다
Share article