JPA

yenn·2021년 8월 4일
0

Spring

목록 보기
9/12
post-thumbnail

JPA

  • JPA 는 기존의 반복 코드 뿐만 아니라, 기본적인 SQL query 또한 직접 만들어서 실행
  • JPA 를 사용하면 SQL 과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임으로 전환
  • JPA 를 사용하면 개발 생산성을 높임
  • interface
  • ORM(Object Relation Mapping)

build.gradle

// 추가
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

application.properties

// 추가
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none

JPA Entity Mapping

Member.java

package hello.hellospring.domain;

import javax.persistence.*;

@Entity
public class Member  {
    // IDENTITY :  db 가 id 를 자동 생성해주는 것
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // db 에 있는 column 이름과 mapping 가능
//    @Column(name = "username")
    private String name;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

}

JPA Member Repository

JpaMemberRepository.java

package hello.hellospring.repository;

import hello.hellospring.domain.Member;

import javax.persistence.EntityManager;
import java.util.List;
import java.util.Optional;

public class JpaMemberRepository implements MemberRepository{

    private final EntityManager em;

    // injection 받음
    public JpaMemberRepository(EntityManager em){
        this.em = em;
    }
    @Override
    public Member save(Member member) {
        // insert query 와 setId 까지 전부 실행
        em.persist(member);
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        Member member = em.find(Member.class, id);
        return Optional.ofNullable(member);
    }

    // pk 기반이 아니면 jpql 을 사용
    @Override
    public Optional<Member> findByName(String name) {
        List<Member> result = em.createQuery("select m from Member m where m.name = :name", Member.class).setParameter("name", name).getResultList();
        return result.stream().findAny();
    }

    @Override
    public List<Member> findAll() {

        // 객체지향 sql 사용 (jpql) -> 객체(entity) 를 대상으로 query 를 보냄
        return  em.createQuery("select m from Member m", Member.class).getResultList();
    }
}

서비스 계층에 transaction 추가

MemberService.java 상단에 추가

Spring Data JPA

  • Repository 구현 class 없이 Interface 만으로 개발 가능
  • 기본적인 CRUD 기능 제공
  • 실무에서 관계형 데이터베이스를 사용한다면 스프링 데이터 JPA 는 필수
  • 주의 ) Spring Data JPA 는 JPA 를 편리하게 사용하도록 도와주는 기술이므로 JPA 학습 후에 사용

SpringDataJpaMemberRepository interface

package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

// JpaRepository 가 구현체 생성하여 자동으로 bean 에 등록해줌
public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {

    // Interface 로 편리하게 JPQL 구현
    Optional<Member> findByName(String name);

}

Spring Config

package hello.hellospring;

import hello.hellospring.repository.*;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {

    private final MemberRepository memberRepository;

    @Autowired
    public SpringConfig(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository);
    }
}

Spring Data JPA 제공 기능

  • Interface 를 통한 기본적인 CRUD
  • method 이름만으로 조회 기능 제공
  • 페이징 기능 자동 제공

실무에서는 Spring Data JPA 와 JPA 를 기본적으로 사용하고, 복잡한 동작 쿼리는 Querydsl 이라는 라이브러리를 사용함 → Querydsl 은 쿼리도 자바코드로 안전하게 작성이 가능하고 동적 쿼리도 편리하게 작성 가능

앞서 말한 조합으로 해결하기 어려운 쿼리는 JPA 가 제공하는 네이티브 쿼리를 사용하거나 Jdbc Template 를 사용하면 됨

profile
Junior BackendEngineer 😎

0개의 댓글