Spring MVC [JPA]

손정훈·2023년 2월 23일
0

Spring MVC

목록 보기
3/5

JPA

Java 진영에서 사용하는 ORM 기술의 표준 사양

영속성 컨텍스트

JPA에서는 테이블과 매핑되는 엔티티 객체 정보를 영속성 컨텍스트라는 곳에 보관해서 애플리케이션 내에서 오래 지속 되도록 함


JAP API 사용하기

JAP API를 사용하기 위한 사전준비

build.gradle 설정

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa' // (1)
	compileOnly 'org.projectlombok:lombok'
	runtimeOnly 'com.h2database:h2'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

JPA 설정 (application.yml)

spring:
  h2:
    console:
      enabled: true
      path: /h2     
  datasource:
    url: jdbc:h2:mem:test
  jpa:
    hibernate:
      ddl-auto: create  # (1) 스키마 자동 생성
    show-sql: true      # (2) SQL 쿼리 출력

configuration 클래스 생성 (샘플코드 실행)

// (1) Spring에서 Bean 검색 대상인 Configuration 클래스로 간주
@Configuration
public class JpaBasicConfig {
    private EntityManager em;
    private EntityTransaction tx;

		// (2) 리턴하는 객체를 Spring Bean으로 추가
    @Bean
    public CommandLineRunner testJpaBasicRunner(EntityManagerFactory emFactory) {
        this.em = emFactory.createEntityManager();
        this.tx = em.getTransaction();

        return args -> {
            // (3) 이 곳에 학습할 코드를 타이핑합니다.
        };
    }
}

영속성 컨텍스트에 엔티티 저장

import lombok.Getter;

import javax.persistence.*;

@Getter
@Setter
@NoArgsConstructor
@Entity  // (1) 
public class Member {
    @Id  // (2) JPA에서 해당 클래스를 엔티티 클래스로 인식하게 만듦
    @GeneratedValue  // (3) 데이터베이스 테이블에서 기본키가 되는 식별자를 자동으로 설정
    private Long memberId;

    private String email;

    public Member(String email) {
        this.email = email;
    }
}

영속성 컨텍스트와 테이블에 엔티티 저장

@Configuration
public class JpaBasicConfig {
    private EntityManager em;
    private EntityTransaction tx;

    @Bean
    // EntityManagerFactory 객체를 Spring으로부터 DI 받음
    public CommandLineRunner testJpaBasicRunner(EntityManagerFactory emFactory) {	
    	// EntityManager 클래스의 객체를 얻어옴
        this.em = emFactory.createEntityManager();
        
        // Transaction 객체를 얻음
        this.tx = em.getTransaction();

        return args -> {
            example02();
        };
    }

    private void example02() {
    	//  Transaction을 시작하기 위해서 tx.begin() 메서드를 먼저 호출
        tx.begin();
        Member member = new Member("hgd@gmail.com");
		
        // 영속성 컨텍스트에 member 객체의 정보들을 저장
        em.persist(member);

		//영속성 컨텍스트에 저장되어 있는 객체를 데이터베이스의 테이블에 저장
        tx.commit();
		
        // 객체가 잘 저장되었는지 find(Member.class, 1L) 메서드로 조회
        Member resultMember1 = em.find(Member.class, 1L);

        System.out.println("Id: " + resultMember1.getMemberId() + ", email: " + resultMember1.getEmail());

    }
}

엔티티 매핑

@Table(name = "USERS") // 테이블 이름을 설정
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long memberId;
    
    @Column(nullable = false, updatable = false, unique = true)
    private String email;
    
    @Column(nullable = false)
    private LocalDateTime createdAt = LocalDateTime.now();   // 시간 및 날짜를 매핑하기 위한 필드
    
    @Enumerated(EnumType.STRING)  // enum 타입과 매핑할 때 사용하는 애너테이션
    private OrderStatus orderStatus = OrderStatus.ORDER_REQUEST;
}

Id

  • 기본키 직접 할당: 애플리케이션 코드 상에서 기본키를 직접 할당
  • IDENTITY: 기본키 생성을 데이터베이스에 위임
  • SEQUENCE: 데이터베이스에서 제공하는 시퀀스를 사용해서 기본키를 생성
  • TABLE: 별도의 키 생성 테이블을 사용

Column

  • nullable: 열에 null 값을 허용할지 여부
  • updatable: 열 데이터를 수정할 수 있는지 여부
  • unique: 하나의 열에 unique 유니크 제약 조건을 설정

엔티티간 연관 관계 매핑

단방향 연관 관계 (일대다)

단방향 연관 관계 (다대일)

양방향 연관 관계


다대일 연관관계 매핑 코드

public class Order {
	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long orderId;

    @Enumerated(EnumType.STRING)
    private OrderStatus orderStatus = OrderStatus.ORDER_REQUEST;
    @ManyToOne  
    @JoinColumn(name = "MEMBER_ID")
    private Member member;
    
    public enum OrderStatus {
        ORDER_REQUEST(1, "주문 요청"),
        ORDER_CONFIRM(2, "주문 확정"),

        @Getter
        private int stepNumber;

        @Getter
        private String stepDescription;

        OrderStatus(int stepNumber, String stepDescription) {
            this.stepNumber = stepNumber;
            this.stepDescription = stepDescription;
        }
    }
}

다대일 매핑에 일대다 매핑 추가

public class Member {
	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long memberId;

    @Column(nullable = false, updatable = false, unique = true)
    private String email;
    
    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<>();
}

0개의 댓글