[해커톤] CRUD (1) - JPA, Entity, Repository

Kyeong Ju·2022년 8월 20일
0

프로젝트 - bliond

목록 보기
5/8

JPA (Java Persistence API)

JPA는 자바 표준 ORM(Object Relational Mapping)이다.
JPA를 통해 쿼리문 대신 자바 코드를 통해 DB의 데이터를 다룰 수 있다.


Entity

1. Entity란?

엔티티는 데이터베이스 테이블과 매핑되는 자바 클래스를 말한다.
ERD를 통해 구성한 DB의 구조대로 엔티티를 작성하면 된다.
엔티티로 만들 클래스에 @Entity 어노테이션을 붙이면 그 클래스를 엔티티로 사용할 수 있다.

2. Entity v.s. Dto

@Setterbusiness logic특징
entityXODB 테이블 매칭
dtoOX계층간 데이터 전달 (ex. view와 controller 사이)

3. @Builder

엔티티의 경우 값을 함부러 변경하여 일관성과 안전성을 해치면 안되기 때문에 @Setter 어노테이션 사용을 지양한다. 따라서 대신 사용하는 것이 Lombok의 @Builder 어노테이션이다. @Builder를 사용할 경우 자동으로 builder 패턴을 생성해준다.


Repository

1. Repository

리포지터리는 DB의 데이터를 처리하기 위한 인터페이스다. 엔티티는 단순히 DB와 매핑이 되는 클래스이기 때문에 실질적으로 데이터를 가져오고 처리하는 동작들은 리포지터리에서 이루어진다.

// QuestionRepository.java
public interface QuestionRepository extends JpaRepository<Question, Integer> {

}

1.1 JpaRepository 상속

interface QuestionRepository extends JpaRepository

QuestionRepository 인터페이스가 리포지터리가 되기 위하여 JpaRepository 인터페이스를 상속받아야 한다.

1.2 대상 Entity 지정

<Question, Long>

JpaRepository를 생성하기 위하여 <엔티티 타입, 해당 엔티티의 PK 속성의 타입>을 지정해준다. 따라서 이 경우 "Question 테이블" 과 Question 테이블의 PK인 id의 타입인 "Long" 를 적어준다.


2. Repository test

2.1 데이터 저장

// SbbApplicationTests.java

@SpringBootTest
class SbbApplicationTests {

    @Autowired // questionRepository 객체를 자동 생성
    private QuestionRepository questionRepository;

    @Test
    void testJpa() {        
        Question q1 = new Question();
        q1.setSubject("제목 설정");
        q1.setContent("내용 설정");
        q1.setCreateDate(LocalDateTime.now()); // 현재 시간 저장
        this.questionRepository.save(q1); // 저장

        Question q2 = new Question();
        q2.setSubject("제목 설정2");
        q2.setContent("내용 설정2");
        q2.setCreateDate(LocalDateTime.now());
        this.questionRepository.save(q2); 
    }
}

2.2 데이터 조회

// findAll
List<Question> all = this.questionRepository.findAll();
        assertEquals(2, all.size());
        
// findBy + ()
// QuestionRepository.java 에 Question findBySubject(String subject); 추가
Question q = this.questionRepository.findBySubject("sbb가 무엇인가요?");
        assertEquals(1, q.getId());
  • findBy + 엔티티의 속성명
    JPA가 알아서 메서드를 분석해 쿼리를 생성해 처리해준다.
    여러개의 속성에 대한 조건을 한 번에 처리할 수도 있다.
    ex) findBySubjectAndContent / findBySubjectOrContent / ...

2.3 데이터 수정

Optional<Question> oq = this.questionRepository.findById(1);
        assertTrue(oq.isPresent());
        Question q = oq.get();
        q.setSubject("수정된 제목");
        this.questionRepository.save(q);

이미 저장되어 있는 값을 get으로 가져와 set으로 값을 변경하고 save를 하면 Update 쿼리가 실행된다.
( Optional : null 처리를 유연하게 처리하기 위함 )

2.4 데이터 삭제

assertEquals(2, this.questionRepository.count());
        Optional<Question> oq = this.questionRepository.findById(1);
        assertTrue(oq.isPresent());
        Question q = oq.get();
        this.questionRepository.delete(q);
        assertEquals(1, this.questionRepository.count());

delete()를 통해 데이터를 삭제할 수 있다.
앞뒤에 count()를 통해 데이터 수의 변화를 확인할 수 있다.

2.5 @Transactional 어노테이션

테스트 코드에서는 DB 연결이 끊어지는 문제가 발생한다. 따라서 메서드가 종료될 때까지 DB 세션이 유지하기 위하여 @Transactional 어노테이션을 사용한다. (실제 환경에서는 DB 연결이 끊기지 않아 사용하지 않아도 된다.)



참고
점프 투 스트링부트 : https://wikidocs.net/161165
점프 투 스프링부트 : https://wikidocs.net/160890
빌더 패턴 : https://velog.io/@park2348190/Lombok-Builder의-동작-원리

profile
백엔드 취준생

0개의 댓글