SEB[JPA]

Jogi's 코딩 일기장·2021년 9월 3일
0


이번 유닛에서는 java 환경에서 SQL을 다룰 수 있는 기술인 JPA에 대해서 학습과 실습을 진행했다. Spring과 함께 데이터베이스를 java로 다루는 연습을 했는데 꽤 좋은 것 같으면서도 어려웠었던 것 같다. 학습을 하면서 배웠던 개념들을 정리를 해보겠다.

JPA

  • JPA는 JJava Persistence API의 약자로, java에서의 ORM 기술 표준으로, 인터페이스의 모음이다.

  • JPA를 구현한 대표적인 오픈소스가 Hibernate이다.

  • JPA를 통해 데이터베이스의 CRUD 작업을 수행할 수 있다.

EntityManager

  • JPA를 사용하기 위해서는 EntityManager를 생성해야 한다. 이는 JPA에서 가장 핵심이 되는 객체로 스프링에 컨테이너 객체와 동일한 위치라고 생각할 수 있다.

  • 생성자 주입을 통해 EntityManager를 주입 받을 수 있으며, EntityManager는 스프링에서 자동으로 넣어준다.

  • EntityManager를 통해 데이터베이스와 데이터를 주고 받는 메소드 혹은 클래스에서는 @Transactional 어노테이션을 무조건 선언해주어야 하며, 이는 DB 작업에서 생성되는 트랜잭션을 자동으로 관리해준다.

JPQL

  • 위 그림을 보면 entityManager.createQuery(쿼리문)은 SQL을 직접 작성할 수 있게 해주는 메소드이며, 첫 인자로 SQL문이 들어오며, 두번째 인자는 리턴 되는 Entity 객체 타입이 된다. 그리고 첫 인자로 들어오는 SQL문은 일반적인 SQL문이 아니라 JPQL이다.

CRUD

  • 저장 : entityManager.persist(orders(객체))

  • 조회 : Users findUser = entityManager.find(Users.class, id);

  • 수정 : 해당 객체의 Setter를 이용한다.

  • 삭제 : entityManager.remove(객체);

Entity

  • 엔티티 클래스는 DB의 실제 테이블과 매핑되는 객체이다. 엔티티는 DB와 1:1로 대응되며, 이를 기준으로 생성되기 때문에 테이블이 가지지 않는 컬럼을 필드로 가지고 있으면 안된다. 또한 다른 클래스를 상속받을 수 없고, 인터페이스의 구현체여서도 안된다.

  • 엔티티 클래스는 @Entity 어노테이션을 붙여서 엔티티임을 명시해 주어야 하고, 내부의 필드에서는 @Column, @Id 어노테이션 등을 사용해야 한다.

  • 아래와 같이 사용한다.

연관관계 매핑

  • 위 코드를 보면 연관관계 매핑이 존재한다.

  • @ManyToOne

    • N : 1 연관관계를 표현하는 어노테이션이다.
    • 외래키가 들어가는 부분에, 참조를 보관하는 필드로 매핑하는 방식이다.
    • 속성 또한 존재 한다.
      • cascade : 영속성 전이 기능 (ALL, PERSIST, MERGE, REMOVE, REFRESH, DETACH)
      • fetch : global fetch 전략 설정 (즉시로딩, 지연로딩)
      • optional : false 설정 시, 연관된 객체가 반드시 있어야 한다. (기본값: true)
  • @JoinColumn

    • 외래키를 매핑할 때 사용한다. 생략할 경우 필드명에 따라 자동으로 매핑한다.
  • 양방향 연관관계 매핑을 위해서는 한 쪽에서 연관관계가 매핑됐으면 대응되면 쪽에서도 매핑을 해야 한다. @ManyToOne으로 매핑을 해왔다면, 대응되는 쪽에서는 @OneToMany를 통해서 1 : N 관계를 가진다는 것을 명시해야 한다. 그리고 여기에서는 읽기만 가능하며, 옵션으로 mappedBy가 오게 되는데 들어가는 값은 매핑을 해온 필드의 필드명이 된다.

실습

실습은 전에 React를 통해서 만들어봤던 마켓 앱을 사용해 해당 데이터를 데이터베이스로 관리하는 방법을 실습했다. 두 개의 레포지토리를 각 기능에 맞게 구현을 해주면 됐다.
1) 데이터베이스 구조

2) ItemRepository

  • 마켓을 열었을 때 상품들이 보이는 화면에서의 데이터 관리 구현이다. 화면에서는 상품들을 모두 보여주면 되기 때문에 엔티티매니저를 통한 JPQL을 통해서 쉽게 구현할 수 있었다.

  • 엔티티매니저를 사용하기 때문에 메소드위에 @Transactional어노테이션을 사용했다.

3) OrderRepository
1. 주문 내역 만들기

  • 우선 유저 id와 orderDTO와 총 가격이 인자로 들어온다. 여기에서는 유저id를 통해서 데이터베이스에 유저를 찾아야 하기 때문에 find와 id를 통해서 유저를 찾아주었다. 그리고 새로운 order객체를 만들어주고, 그것을 다시 데이터베이스에 persist를 통해서 저장해준다. 그 후에는 리스트를 탐색하면서 새로운 OrderItems 객체를 만들어 주어 데이터베이스에 저장을 해주면 주문내역은 데이터베이스에서 관리가 되는 것이다.
  1. 주문 내역 가져오기
  • 우선 데이터베이스 구조를 보면 OrderItems를 통해 Orders와 Items에 접근할 수 있으므로 양방향 매핑 관계를 만들어 줘야 한다. 그러기 위해서는 엔티티 클래스에서 @ManyToOne, @OneToMany를 통해서 매핑을 해주어야 한다.

  • JPQL을 통해서 OrderItems와 Items, Orders를 조인하고 Orders는 Users와 연관관계가 있으므로 Orders에서 user_id가 인자로 들어온 id와 같다면 SELECT를 해서 원하는 데이터를 가져올 수 있다.

  • 또한 JPQL에서는 데이터베이스에서의 컬럼명이 아닌 엔티티클래스에서 선언한 필드명으로 매핑을 해주어야 한다. 이렇게 해주어도 JPA에서 변환을 해주어 데이트베이스에 올라가게 된다.

  • 리스트를 리턴하는 것을 보면 자료형이 OrdersResDTO라는 것을 알 수 있는데 이는 엔티티가 아니다. 그리고 query.getResultList()를 통해 데이터가 저장되는 것을 보면 각 컬럼들이 Object의 배열로 이루어져있는 것을 알 수 있다. 각각은 자료형을 가지고 있지만 이를 변환을 못해준 것 같다. 그래서 리스트를 돌면서 setter를 통해 OrdersResDTO를 설정해주고 결과 리스트에 추가해주는 작업을 해주었다. 사실 쿼리를 통해서 OrdersResDTO의 형태로 뽑아주면 좋겠지만 이 방법은 더 찾아봐야 할 것 같다.

4) 느낀점

  • Java를 통해서 데이터베이스를 관리한다는 것이 정말 편하게 느껴졌다. 하지만 아직 제대로 사용할 줄 모르는 것 같아서 조금 더 실습을 하고 익혀야 능숙하게 다룰 수 있을 것 같다. 또한 프로젝트를 하면서 많이 쓰게 될텐데 이번 유닛에서 배운 것들을 잘 숙지해야 할 것 같다.

Reference

  • 코드스테이츠 강의자료
profile
프로그래머로서의 한걸음

0개의 댓글