스프링부트 독학-5장 데이터베이스와 조작인 편해지는 ORM

jaegeunsong97·2023년 8월 31일
0

출처

신서영개발자님의 스프링부트 책

새롭게 알게된 내용 정리

데이터베이스

  • 데이터베이스 관리자 : DBMS(Database Management System)
    • 데이터베이스는 많은 사람이 공유할 수 있어야 하므로 동시 접근을 할 수 있어야함
    • 따라서 관리가 필요
    • DBMS 관리 특징에 따라 분류 : 관계형, 객체-관계형, 도큐먼트형, 비관계형
    • 관계형 DBMS : RDBMS(Relation Database Management System)
      • 관계형이라고 하는 이유 : DBMS가 관계형 모델을 기반을 하기 때문
      • 테이블 형태Key, Value 형태
    • H2, MySQL
      • H2 : 자바로 작성된 RDBMS
        • 스프링 부트가 지원하는 인메모리 관계형 데이터베이스
        • 데이터를 다른 공간에 보관하는 것이 아닌 애플리케이션 내부에 데이터를 저장
        • 따라서 애플리케이션 재실행? 전부 리셋
        • 그래서 개발 테스트용으로 많이 사용
    • 데이터베이스 용어
      • 테이블 : 데이터베이스에서 데이터를 구성하는 가장 기본적인 단위
      • : row, record
        • 고유한 식별자 필요 Primary Key
        • <-------------------->
      • : column
        • 각 요소에 대한 속성을 가짐
        • 따라서 무결성을 보장
        • Height Column에 숫자가 들어오지 한글이 들어오면 무결성 터짐
      • 기본키 : 행을 구분하는 식별자
        • 수정이 되면 안됨 + 유효한 값
        • 따라서 NOT NULL
      • 쿼리 : SQL DB 전용 언어 사용

ORM

  • ORM : Object Relation Mapping
    • 자바의 객체와 데이터베이스를 연결하는 프로그램
    • 객체와 데이터베이스를 연결자바 언어로만 데이터베이스를 다룰 수 있게 하는 도구
    • DB내용을 ORM하면 JAVA에서 사용하는 것(쉽게)
    • ORM 장단점
      • 장점
        • SQL을 직접 작성하지 않고 사용하는 언어로 DB 접근
        • 객체지향적으로 코드를 작성할 수 있기 때문에 비즈니스 로직에만 집중
        • DB 시스템이 추상화 -> MySQL에서 PostgreSQL전환시 추가 작업 거의 없음 DB 시스템에 대한 종속성 감소
        • Mapping하는 정보 명확하게 있어서 ERD에 대한 의존도 낮고 유지보수 유리
      • 단점
        • 프로그램 복잡성 증가 -> 난이도 증가
        • 복잡하고 무거운 쿼리 -> ORM으로 해결 불가능

JPA와 하이버네이트

  • JPA : Java Persistance API

    • 자바에서 관계형 DB를 사용하는 방식을 정의한 인터페이스
    • 인터페이스이기 때문에, ORM 프레임워크 필요 : 하이버네이트
      • 하이버네이트 : JPA 인터페이스를 구현한 구현체이자 자바용 ORM 프레임워크
        • 내부적으로 JDBC API 사용
        • 목표 : 자바 객체를 통해 DB 종류에 상관없이 DB를 자유자재로 사용할 수 있게 함
    • JPA, 하이버네이트 역할
      • JPA : 자바 객체와 DB를 연결데이터를 관리
      • 하이버네이트 : JPA의 인터페이스 구현
  • Entity Manager

    • Entity : DB의 테이블과 매핑되는 객체
      • DB의 테이블직접 연결
    • Entity Manager : 엔티티를 관리해, DB와 애플리케이션 사이에서 객체를 생성, 수정, 삭제하는 등의 역할
      • 스프링 부트 내부에서 Entity Manager Factory 1개생성해서 관리
      • @PersistanceContext 또는 @Autowired엔티티 매니저 사용
      • 스프링 부트는 기본적으로 Bean을 1개만 생성해서 공유 -> 동시성 문제 가능
        • 따라서 Entity Manager가 아닌 Proxy Entity Manager를 사용
        • 필요할 때 DB 트랜젝션과 관련된 실제 Entity Manager 호출
        • 즉, Spring Data JPA에서 Entity Manager를 알아서 관리해준다
@PersistanceContext
EntityManager em; // Proxy Entity Manager, 필요할 때 진짜 Entity Manager 생성
  • 영속성 컨텍스트 : Persistance Context
    • Entity Manager는 Entity를 Persistance Context에 저장
    • JPA에서 매우매우매우매우 중요한 Persistance Context
    • 특징 : 공통점DB접근 최소화해서 성능 향상
      • 1차 캐싱
        • Persistance Context는 내부에 1차 캐시를 가짐
          • 캐시 키 : @Id 붙어있는 것 식별자
        • 값이 있다 : 1차 캐시에서 반환
        • 값이 없다 : DB에서 조회해 1차 캐시에 저장 후 반환
        • 캐싱의 유무에 따라 DB에서 가져오는 속도 다름
      • 쓰기 지연 : transactiona write behind
        • 트랜잭션을 커밋하기 전까지 DB에 보내지 않고, 트랜젝션이 커밋되는 시점에 한번에 쿼리를 실행
        • 적당한 묶음으로 쿼리를 요청 -> DB 시스템 부담 줄임
      • 변경 감지
        • 트랜젝션을 커밋하면 1차 캐시에 저장되어 있는 엔티티의 값과 현재 엔티티값 비교
        • 다른경우, DB에 자동으로 반영
        • 쓰기 지연과 마찬가지로 적당한 묶음으로 쿼리를 요청 -> DB 시스템 부담 줄임
      • 지연 로딩 : LAZY <-> EAGER
        • 쿼리로 요청한 데이터를 애플리케이션에 바로 로딩하는 것이 아니라 필요할 때 지연로딩 하는 것
    • 엔티티의 상태
      • 분리상태 : detached
        • 영속성 컨텍스트가 관리하고 있지 않음
      • 관리상태 : managed
        • 영속성 컨텍스트가 관리
      • 비영속상태 : trasient
        • 영속성 컨텍스트와 전혀 관계 X
      • 삭제상태 : removed
        • 영속성 컨텍스트와 DB에서 완전 삭제
public class EntityManagerTest {
    
    @Autowired
    EntityManager em;
    
    public void example() {
        Member member = new Member(1L, "홍길동"); // 비영속
        em.persist(member); // 관리
        em.detach(member); // 분리
        em.remove(member); // 삭제
    }
}

스프링 데이터와 스프링 데이터 JPA

  • 스프링 데이터

    • 비즈니스 로직에 집중하기 위해, DB사용 기능을 클래스 레벨에서 추상화
    • 스프링 데이터에서 제공하는 인테페이스를 통해 스프링 데이터를 사용할 수 있음
    • 해당 인터페이스 CRUD 모두 포함 -> 알아서 쿼리 생성
    • 페이징 처리 기능, 네임드 쿼리 기능 포함
  • 스프링 데이터 JPA

    • 스프링 데이터의 공통적인 기능에서 JPA의 유용한 기술이 추가된 것
    • 스프링 데이터의 인터페이스 PagingAndSortingRepository상속받아 JpaRepository 인터페이스 만듬
    • JpaRepository 인터페이스를 Repository가 상속받으면 끝

코드

@Getter
@Entity // Member 객체를 JPA가 관리하는 엔티티로 지정 -> DB와 매핑
@NoArgsConstructor(access = AccessLevel.PROTECTED) // 안전하게
@AllArgsConstructor
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 자동증가 전략
    @Column(name = "id", updatable = false)
    private Long id;

    @Column(name = "name", nullable = false)
    private String name;
}
profile
블로그 이전 : https://medium.com/@jaegeunsong97

0개의 댓글