본문 바로가기
study/Spring

JPA란 무엇인가?

by 고기만두(개발자) 2021. 9. 11. 17:36
728x90
반응형

사실 그간 자바나 관련 공부를 하면서, 실무에서 JDBC를 통해 데이터베이스와 프로그램을 연결했었다.

안 그런 적이 한 번도 없었는데, 그럴 필요가 없다고 해서 급하게 공부하고 글을 쪄봤다.

 

복되는 코드를 줄이고, "기본적인 SQL을 직접 만들어서 실행"까지 해주는 게 있다? 이게 JPA다.

 

ORM(Object-Relational Mapping)을 먼저 알아야 한다.

객체와 관계형데이터베이스를 별도로 설계해주는 방법을 총칭한다.

예전에는, 그리고 사실 내 지금 실무에서는 EJB 기반의 희한한 프레임워크를 사용하고 있다...

근데 이게 되게 복잡하고 지저분하고, 그렇다고 한다.

사실 일하면서 프레임워크 자체를 까볼 생각은 자주 해보지 않는 편이다.. 궁금해해본 적 없긴 하다.

 

그리하여 요즘 대세는 JPA(Java Persistence API)라는, 일련의 인터페이스들의 모음집이 되었다더라는.. 그런 흐름이다.

한마디로, JDBC를 일일이 날코딩으로 설정해서 붙이지 않아도 된다는 얘기다.

JPA 중 가장 대표적인 게 Hibernate인데

hibernate라든가, ejb의 구조 등은 너무 옆길로 새 버릴 것 같으니 이건 나중에.

 

dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
  implementation 'org.springframework.boot:spring-boot-starter-web'
  //implementation 'org.springframework.boot:spring-boot-starter-jdbc'
  implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
  runtimeOnly 'com.h2database:h2'
  testImplementation('org.springframework.boot:spring-boot-starter-test') {
  	exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
  }
}

build.gradle 설정파일에서 jdbc를 지워버려도 무방하다.

spring-boot-starter-data-jpa가 jdbc관련 라이브러리를 포함한다.

 

spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none

application.properties 설정 파일에서 설정값을 몇 개 더 추가하였다. 위 3줄은 db연결 관련된 거니까 무시해도 무방

show-sql : JPA가 생성하는 SQL을 출력해서 보여주는 설정

ddl-auto = none : JPA가 원래 테이블도 자동으로 생성하는데, 그 기능은 굳이 필요없으니 끄도록 하자.

이미 테이블을 만들어놓은 상태였음

//member.java - 엔티티 맵핑

package hello.hellospring.domain;
import javax.persistence.*;

@Entity
public class Member {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    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.java - 회원 리포지토리에서 실제 JPA 사용

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;

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

    @Override
    public Member save(Member member) {
        em.persist(member);
        return member;
    }

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

    @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() {
        return em.createQuery("select m from Member m", Member.class).getResultList();
    }
}

//MemberService.java - 서비스 계층에 트랜잭션을 추가하여
//JPA를 통한 데이터 변경을 트랜잭션 안에서 진행할 수 있도록 함

import org.springframework.transaction.annotation.Transactional
@Transactional
public class MemberService {
//후략


//SpringConfig.java
//스프링 데이터 JPA가 SpringDataJpaMemberRepository를 사용하도록 설정 변경

package hello.hellospring.service;

import hello.hellospring.repository.*;
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 final MemberRepository memberRepository;

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

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

}

 

몇 가지 설정을 맞춰놓고 createQuery에 필요한 쿼리를 입력만 하면

간단하게 DB와 연결하여 조회/입력 기능을 수행할 수 있다.

복잡한 동적쿼리가 필요해도 Querydsl 라이브러리를 사용하여 자바 코드 베이스로 안전하게 쿼리를 작성하여 연결할 수 있다. 뭐 그걸로 안 되면 JPA 네이티브 쿼리나 스프링의 JdbcTemplate를 사용해도 무방하고..

 

맨날 쿼리 직접 짜고, 연결하고.. 하던 거에 비해서 너무 쉽잖아?

 

그런데 더 쉬운게 또 있다.

 

스프링 데이터 JPA 를 활용하면, 메서드 이름만을 가지고 인터페이스에서 기본적인 CRUD 가 가능해진다.

이미 어느정도 기본적인 메소드가 다 갖춰져 있다. 심지어 페이징도 CRUD도 파생 repository에서 제공해주네?

와.. 핵쉽다 진짜. 왜 이걸 모르고 살았지?

근데 스프링데이터JPA만 복붙복붙해서 쓰자니, JPA 자체에 대해서도 앞으로 공부할 게 엄청 많아질 것 같다.

 

 

사족.

글 써놓고 보니까 내가 지금까지 n년동안 한 게 그냥 코딩 단순노동이었던 건가 싶다.

대체 언제적 기술을 아직도 쓰고 있는 거지?

공부를 하면 할 수록 할 게 늘어나는 기분, 점점 고여가는 기분이다.

 

*출처, 듣고 있는 강의 - 인프런_ 스프링 입문 - 코드로 배우는 스프링부트, 웹MVC, DB접근기술

앞광고 뒷광고 아님 주의 - 해당 강의는 무료강의임. 업체나 강사로부터는 한 푼도 받지 않았음.

나에게 작고 귀여운 돈을 주는 회사에서 해당 사이트와 제휴를 맺고 있을 뿐임..

728x90
반응형

댓글