스프링 DB 접근 기술- JPA

2022. 8. 5. 23:462022/Spring

JPA

JDBC에서 JDBC Template으로 바뀌면서 개발자가 작성해야하는 반복된 코드는 확 줄었지만 SQL은 직접 모두 작성해야했다. 그런데 JPA는 이런 기본 SQL도 직접 만들어서 실행해준다.

또한 SQL과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임을 전환할 수 있다. 따라서 개발 생산성을 높일 수 있게된다.

 

마치 객체를 메모리(memoryMemberRepository)에 넣듯이 JPA가 중간에서 DB에 SQL을 날리고, DB에서 데이터를 가져오는 것을 처리한다.

 

JPA 라이브러리 추가 및 설정

 

data-jpa 라이브러리 추가
1. JPA가 날리는 SQL을 볼 수 있음, 2. 객체를 보고 테이블을 만들어줌(create)

 

Entity 맵핑

JPA는 인터페이스만 제공이 되는 것이다. hybernate, eclipse 등이 구현 기술이 된다. 즉, JPA 인터페이스에 hybernate만 사용한다고 생각해도 무방하다. - jpa, hybernate 라이브러리가 있는지 확인

 

JPA는 객체와 ORM(Object, Relational DB, Mapping(by @))의 기술이다.

package hello.hellospring.domain;

import javax.persistence.*;

//jpa가 관리하는 entity
@Entity
public class Member {
    //PK 값, DB에서 자동 생성되는 값 = Identity 전략
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; //시스템이 정하는 임의의 값
    //DB의 컬럼명이랑 맵핑
	//@Column(name = "username")
    private String name;

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

 

JpaMemberRepository
package hello.hellospring.repositroy;

import hello.hellospring.domain.Member;

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

public class JpaMemberRepository implements MemberRepository{
    //JPA는 Entity Manager 라는 것으로 모든 것이 동작
    // Spring boot가 자동으로 entity mamager라는 것을 생성함 - 내부적으로 DataSource를 모두 가지고 있어서 DB와의 통신 등을 다 처리한다.
    private final EntityManager em;

    public JpaMemberRepository(EntityManager em){
        this.em = em;
    }

    @Override
    public Member save(Member member) {
        //JPA가 insert 쿼리 만들어 DB에 집어넣고, set ID까지 다 해준다.
        em.persist(member);
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        //PK
        //조회할 타입, 식별자
        Member member = em.find(Member.class, id);
        return Optional.ofNullable(member);
    }

    // List를 가지고 조회할 때는 쿼리를 짜야한다. (PK 기반이 아닌 경우, JPQL 써야함)
    // JPA 기술을 spring에서 한번 감싸고 제공하는 기술 = spring data jpa 기술 : 아래 예제 마저 쿼리 안짜도 된다.
    @Override
    public Optional<Member> findByName(String name) {
        // JPQL이라는 객체지향 쿼리 언어를 사용해야한다.
        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() {
        //select m from Member m : 테이블이 아닌 객체(Entity)를 대상으로 쿼리를 날림
        return em.createQuery("select m from Member m", Member.class)
                .getResultList();
    }
}

 

@Transactional 추가 

 

SpringConfig 변경
package hello.hellospring;

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

import javax.persistence.EntityManager;
import javax.sql.DataSource;


@Configuration
public class SpringConfig {

    private EntityManager em;

    //DI
    @Autowired
    public SpringConfig(EntityManager em){
        this.em = em;
    }


    //Configuration을 읽고 스프링 Bean으로 등록하도록 인식
    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository(){
        //구현체 반환
        return new JpaMemberRepository(em);
    }
}

 

테스트

localhost:8080에서 테스트를 해보면 다음과 같은 로그가 나온다.

즉, Hibernate 구현체가 알아서 SQL을 날려 데이터를 insert한다는 것을 알 수 있다.