JPA(Java Persistence API)

Shinyoung Archive 저장소·2022년 1월 12일
0

ORM이란?(Object-Relational Mapping)

  • 객체가 테이블이 되도록 매핑 시켜주는 프레임워크
  • 객체와 관계형데이터베이스 매핑, 객체와 DB의 테이블이 매핑을 이루는 것
  • 프로그램의 복잡도를 줄이고 자바 객체와 쿼리를 분리할 수 있으며 트랜잭션 처리나 기타 데이터베이스 관련 작업들을 좀 더 편리하게 처리할 수 있는 방법
  • SQL Query가 아닌 직관적인 코드(메서드)로서 데이터를 조작할 수 있다.
    ex) 기존쿼리 : SELECT * FROM MEMBER; 이를 ORM을 사용하면 Member테이블과 매핑된 객체가 member라고 할 때, member.findAll()이라는 메서드 호출로 데이터 조회가 가능

JPA란?

✅ JPA란 DB 테이블과 자바 객체 사이의 매핑을 처리해주는 ORM이란 기술의 표준. 객체와 DB 사이의 매핑을 어떻게 설정하고 어떻게 동작해야하는지 기술. 즉 자바의 클래스와 DB의 테이블을 매핑하는 기술

하이버네이트(Hibernate)

하이버네이트란 JPA 프로바이더의 한 종류. JPA 프로바이더는 JPA의 표준을 실제로 구현

쉽게 말하자면 JPA는 DB와 자바 객체를 매핑하기 위한 인터페이스(API)를 제공하고 JPA 프로바이더는(하이버네이트) 이 인터페이스를 구현한 것

엔티티(Entity)

엔티티는 영속성을 가진 객체로 db테이블에 보관할 대상. 즉 영속 컨텍스트에 속한 객체

이러한 엔티티는 특정한 시점에 db에 영향을 미치는 쿼리를 실행


  • 엔티티를 설정하기 위한 어노테이션
  • @Entity JPA는 클래스 이름을 테이블 이름으로 사용하는데 아래의 Room 엔티티는 기본적으로 Room 테이블과 매핑 @Entity public class Room { //... }
  • @Table 클래스이름과 테이블의 이름이 다른 경우엔 @Table 애노테이션을 이용하면 클래스이름과 테이블 이름이 다르더라도 name 속성을 설정하여 테이블의 이름을 지정할 수 있다. @Entity @Table(name="room_info") public class Room{ // ... }
  • @Id 기본키 직접 할당. DB가 레코드를 구분하기 위해 주요키를 사용하는 것처럼 JPA는 엔티티의 @Id 애노테이션을 이용하여 식별자를 지정하는데 @Id 애노테이션을 지정한 필드 값은 엔티티를 식별하기 위한 식별자로 사용된다. 예를 들면 아래 코드에서 id = ? 쿼리에서 ? 자리에 @Id 설정한 필드가 사용
    public Optional findRoom(int roomId) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpastart");
        EntityManager em = emf.createEntityManager();
        try {
            Room room = em.find(Room.class, roomId);  // SELECT * FROM Room WHERE id = ?
            return Optional.ofNullable(room);
        } finally {
            em.close();
        }
    }
  • @Enumerated 자바의 Enum타입을 매핑 할 때 사용한다. 열거타입에 대한 매핑
      @Enumerated(EnumType.STRING) -> 문자열로 저장
      private RoleType roleType;
  • @Column 컬럼을 매핑. 프로퍼티의 이름과 테이블의 칼럼 이름이 같다면 생략이 가능하지만, 다를 경우에는 @Column 애노테이션을 지정해줘야 한다. @Entity @Table(name="room_info") public class Room { @Id private String number; private String name; @Column(name="description") private String desc; }
  • @SuppressWarnings 경고를 제외시킬 때 사용. 자바 노란색 경고 무시할 때 @SuppressWarnings({"rawtypes", "unchecked"}) rawtypes : 제너릭을 사용하는 클래스 매개 변수가 불특정일 때의 경고 unchecked : 검증되지 않은 연산자 관련 경고
  • @GeneratedValue 기본키의 생성 방법을 매핑하는 어노테이션(대리키 사용방식) 1) IDENTITY : 기본키 생성을 데이터베이스에 위임(GenerationType.IDENTITY) 2) SEQUENCE : 데이터베이스 시퀀스를 사용해서 기본 키를 할당
    • 사용할 데이터베이스 시퀀스 매핑 → @SequenceGenerator를 사용해서 시퀀스 생성기를 등록하고 시퀀스 키 생성 전략을 GenerationType.SEQUENCE로 설정

      3) TABLE : 키 생성 테이블 사용

    • @TableGenerator 를 사용해서 테이블 키 생성기 등록 및 시퀀스용 테이블과 매핑한 다음 GenerationType.TABLE로 설정

      4) AUTO : 선택한 데이터베이스의 종류에 따라 위 3개 전략 중 하나를 자동으로 선택

  • @Temporal 날짜 타입 매핑. 시간을 나타내는 데이터를 각 DBMS에서 제공하는 시간 관련 데이터와 매핑 (systimestamp date 등)
  • @Lob BLOB, CLOB 타입을 매핑
  • @Transient 특정 필드를 데이터베이스에 매핑하지 않을 때 사용한다. 클래스의 멤버 변수 중 DB 컬럼과 매핑하고 싶지 않은 멤버 변수에 추가하여 매핑 대상에서 제외할 수 있다.
  • @Embedded Composite Value 타입을 지정할 때 쓰이는 어노테이션. 이 Composite Value값은 자바의 클래스 형식으로 작성할 수 있다. @AttributeOverride 어노테이션을 통해서 Composite Value 타입의 멤버 변수를 테이블의 어떤 컬럼과 매칭할지 커스터마이징할 수 있다.
  • @ManyToOne
    • 다대일 관계 매핑
    • 현재 클래스의 엔티티가 @ManyToOne이 붙은 엔티티와 N:1 관계를 맺는 것이라는 정보를
    • 제공하는 어노테이션
    • 자식엔티티 객체에서 부모엔티티 객체를 바라볼 때 사용, FK가 있는 자식엔티티 객체 쪽에 위치
    • 자식엔티티가 조회됨과 동시에 부모엔티티를 조회, 만약 부모엔티티를 바로 사용하지 않는다면 속도를 위해 FetchType을 LAZY로 설정
    • 이 어노테이션이 붙은 테이블의 컬럼을 참조하는 외래키를 생성한다.
    • FetchType 디폴트값 = EAGLE(관계된 엔티티의 정보를 미리 읽어오는 것)
  • @OneToMany
    • 일대다 관계 매핑
    • 여러 건과 관계를 맺을 수 있으므로 컬렉션을 사용해야한다. / Set / Map 등
    • 데이터를 바라보는주체가 부모 엔티티이며 하나의 부모엔티티 데이터와 연관이 있는 여러개의 자식엔티티 데이터를 사용하겠다는 의미
    • 부모엔티티에서 @OneToMany를 지정하게 되며 JPA 관계 중 유일하게 FK가 위치한 자식엔티티가 아닌 부모엔티티에 어노테이션이 위치
    • FethcType 디폴트값 = LAZY(실제로 요청하는 순간 가져오는 것)
  • @JoinColumn 외래키 매핑할 때 사용. name 속성에 매핑할 외래 키 이름 지정

Spring Data JPA

JPA를 더 편리하게 사용할 수 있도록 스프링 프레임워크가 지원하는 프로젝트

CRUD를 처리하기 위한 공통 인터페이스를 제공

인터페이스만 작성하면 실행 시점에 스프링 데이터 JPA가 구현 객체를 동적으로 생성해서 주입해줌 즉, 데이터 접근 계층을 개발할 때 구현 클래스 없이 인터페이스만으로 개발 가능

일반적인 CRUD 메소드(save, find, delete 등)는 JpaRepository 인터페이스만 상속 받아도 공통으로 제공 그리고 아래 코드처럼 findByUsername(String username)처럼 관례에 맞게 메소드 이름을 지어주면 자동으로 스프링 데이터 JPA가 메소드 이름일 분석해 적절한 JPQL을 실행

public interface MemberRepository extends JpaRepository<Member, Long>{ 
	public List<Member> findByUsername(String username);
}
실행되는 JPQL: select m from Member m where username = :username

Repository

엔티티의 기본적인 CRUD가 가능한 JpaRepository 인터페이스 제공


  • save : entity를 저장하는 메소드(insert, update) , 새로운 엔티티는 저장하고 이미 있는 엔티티는 수정하는 메소드
    repository.save(entities)
    PK O : INSERT
    PK X : UPDATE * update할 데이터를 먼저 select 한 후에 update를 해야함, update만 할 경우 null로 들어가는 데이터들이 생김
  • delete : entity를 삭제하는 메소드(delete)
  • flush : EntityManager의 내용을 DB에 동기화하는 메소드
  • saveAndFlush : entity에 대한 저장 작업 후 flush
  • deleteAll : DB의 모든 레코드를 persistence context로 읽어와 삭제하는 메소드
  • deleteInBatch : persistence context로 읽어오지 않고 DB의 모든 레코드를 삭제하는 메소드
  • findOne : primary key로 DB에서 Entity를 찾아오는 메소드(select) // 한 건
  • findAll : 모든 entity를 찾아오는 메소드(select) // 전체 레코드
    repository.finaAll(검색조건) --> List로 받기 때문에 형변환 필요
  • exists : primary key에 해당하는 entity가 존재하는 확인하는 메소드
  • count : entity의 갯수를 확인하는 메소드

Querydsl - BooleanBuilder

쿼리에서 조건부인 where 뒤의 조건을 생성해주는 것

name이 오면 where name = name

//if문으로 필요한 부분만 booleanBuilder에 추가하면서 쿼리르 만든 형태 - 정적쿼리 
//조건이 null이 아니고 문자열이 비어있지 않다면 검색 조건을 추가한다
if(!Strings.isNullOrEmpty(cosNum.get())) {
	booleanBuilder.and(cosMstEntity.id.eq(Long.valueOf(cosNum.get())));
}

//where절에 booleanBuilder 인자를 넘겨 조건 추가
builder.where(booleanBuilder)

[1.참고자료] https://sjh836.tistory.com/189

profile
BE developer 👩‍💻 기록용 🤳

0개의 댓글