[프로그래머스스쿨/자바 웹 백엔드 개발] 2주차

Jiwon·2022년 10월 16일

[프로그래머스스쿨 / API 서버 개발 미션으로 배우는 자바 웹 백엔드 개발] 에서 수강하며 정리한 글 입니다. 문제가 있을 시, 삭제 하겠습니다.

1주차 PR 공통 리뷰

커밋은 작업마다 쪼개는게 좋다.
test 코드 성공 시나리오, 에러 시나리오 있는게 좋다.
@WebMvcTest @MockBean 등 참고해서 사용하면 좋다.
테스트용 DB가 따로 있는게 좋다.

Use tracing 을 체크해서 돌리면 좀 더 찐하게 테스트 할 수 있다고 한다.
true 에 대한 테스트와 false에 대한 테스트가 없다는 것을 알 수 있다.

myner 우리 멘토님 블로그..! 나중에 testcode에 관해서 참고해야지
지금은 안 들어가진다 ㅠ

2주차 JPA(Java Persistence API)

Spring Data JPA는 JPA를 편리하게 사용할 수 있도록 지원하는 프로젝트

Spring Data JPA

  • JpaRepository 인터페이스를 상속 받으면 사용할 수 있는 주요 메소드
  • save : 새로운 엔티티는 저장하고 존재하는 엔티티는 수정
  • delete : 엔티티 삭제
  • findById : 엔티티를 id로 조회
  • findAll : 모든 엔티티 조회(sort, pageable 조건을 파라미터로 제공)

일반 JPA를 쓰면 하나하나 조건을 입력해야 하는데

public interface (Repository) extends JpaRepository<(파람 값, 파람 값)>{
	List<(객체)> find(Jpa메소드)
}

Spring Data JPA를 사용하면 금방 구현이 가능하다.

단, 간단하게 가능하지만 필요시에 따라
JPQL을 직접 선언해야 할 때도 있고, Native Query를 사용하거나 QueryDSL을 사용하기도 한다.

ORM(Object Relational Mapping)

ORM은 사실 JPA다.

  • 객체와 Database는 서로 다른 매커니즘
  • 객체에 맞춰서 모델링하면 매핑작업이 늘어나고 테이블에 맞춰서 모델링하면 객체답게 쓸 수 없다.
  • 객체는 객체처럼, RDB는 RDB처럼
  • ORM이 중간에서 매핑
  • Java진영의 ORM 표준기술 Java Persistence API

객체 -> 저장소 (SQL 변환)
객체 <- 저장소 (객체 변환)

JPA

  • JDBC API 사용

  • 저장시에 Entity 객체를 분석하여 Insert Query를 조회시에는
    Select Query 후에 Entity 객체로 매핑

  • JPA는 인터페이스의 모음이고 구현체로 하이버네이트 등이 있음

  • JPA를 사용하면 객체중심의 설계와 개발이 용이

  • 생산성, 유지보수성, 성능 등의 이점이 있음

  • Select시 같은 트랜잭션 내에서 엔티티 동일성 보장

  • DB Isloation(DB 격리수준)이 Read Commit이어도 어플에서 Repeatable Read 보장

  • 트랜잭션 커밋시 모은 Insert쿼리 실행(쓰기지연)

  • 트랜잭션 커밋시 Update, Delete 실행하고 바로 커밋해서 Row Lock 최소화

  • 객체가 실제 사용될 때 까지 로딩 지연 가능

저장소 신경 안 쓰고 작업하기 위함.

JPA가 저장소 하나 가지고 있다가, find를 써서 바로 DB로 안 가고, 영속성 컨텍스트(entity manager)로 가서 찾아서 넘겨 받는다. 찾는게 없을 때 DB에서 select 해 온다.

@Entity : 객체를 엔티티로 선언한다.
@Table(name="~s") : 테이블 이름 바꿔주기

@Id : 어떤 키를 primaryKey로 둘 지
@GenerateValue : 어떤 값으로 Generated 로 둘 지

@Column : 은 붙여도 되고, 안 붙여도 된다.

extends BaseEntity -> BaseEntity?
@CreatedBy
createdBy : 누가 Entity에 인서트 했는가

@LastModifiedBy
lastModifiedBy : 누가 Entity를 수정 했는가

extends BaseTimeEntity
@CreatedDate
createdDate : 언제 인서트 했는가

@LastModifiedDate
lastModifiedDate : 언제 수정 했는가

@MappedSuperclass : 그냥 엔티티가 아니라 상위개념으로 쓸거다

@Enumerated
: enum 타입을 사용한다는 것
@Temporal
: 날짜 타입을 매핑할 때 사용
@Lob
: 데이터베이스의 BLOB, CLOB타입 과 매핑
@Transient
: Entity에서 매핑되지 않는 필드로 DB에 저장, 조회가 되지 않는다
@Access
: JPA가 엔티티에 접근하는 방식을 나타낸다

연관관계

객체는 필드로 참조 -> 객체의 참조와 테이블의 외래키의 차이점을 매핑

단방향, 양방향 객체 참조가 존재하고,
양방향의 경우 연관관계를 관리하는 연관관계 주인이 존재.

연관관계 주인은 '다(Many)' 쪽 이다.

@ManyToOne
: 다대일
@OneToMany
: 일대다
@OneToOne
: 일대일
@ManyToMany
: 다대다
ManyToMany 같은 경우는 중간에 객체를 하나 빼서 중간객체를 만들어 주는걸 권장한다.

양방향의 경우 toString(), json라이브러리, lombok을 조심
-> 무한루프에 빠질 수 있다.

eager 로딩, lazy 로딩

jap에서는 연관 객체를 상속받은 proxy 객체를 반환하고,
해당 객체를 호출할 때 proxy 내부의 실제 객체 호출

  • proxy 객체는 처음 사용할 때 한 번 초기화

proxy 객체를 사용시에는 타입체크시 주의

  • == 비교는 실패한다. instance of 사용해야함

영속성 컨텍스트와 상관없는 상태의 경우(ex: 준영속) proxy 객체를 사용하면 예외 발생

FetchType.LAZY : 지연로딩
->proxy를 사용하여 필요시점에 초기화(DB조회)
FetchType.EAGER : 즉시로딩
가급적 지연 로딩을 사용하자.

N+1 해결책 : fetch join

일대다 관계에서 페치조인의 경우 중복된 데이터가 생길 수 있다.

profile
과연 나는 ?

2개의 댓글

comment-user-thumbnail
2022년 10월 18일

이제 JPA 고수?

1개의 답글