JPA 연동하기

JDK : 1.8
Spring Boot : 2.3.1

JPA : Hibernate

DBMS : MySQL

 

오늘은 JPA연동하는 방법에 대해서 포스팅을 하려고합니다.

단순 연동 방법이 필요하신 분들은 서론을 건너뛰고 보시면 될 것같습니다.

JPA란?

JPA란 MyBatis랑 비슷하게 DB와 서버의 연결을 간편하게 해주는 인터페이스입니다. 하지만 Mybatis와 다르게 엔티티에 직접 테이블과 컬럼을 지정하고 쿼리문을 객체지향적으로 코딩할 수 있게 도와줍니다.

 

JPA의 구성

JPA의 역할을 이해하기 쉽도록 그림을 한장 퍼왔습니다. 위 설명과 조합하시면 이해가 빠르실 것 같습니다.

출처 : https://velog.io/@tmdgh0221/JPA-%EA%B8%B0%EB%B3%B8%ED%8E%B8-%EC%A0%95%EB%A6%AC

그림을 보시면 JPA라는 인터페이스로 JDBC를 감싸고 있습니다. 저희가 JPA의 함수와 문법을 이용해서 쿼리문을 날려달라고 요청하면, JPA는 JDBC에 맞게 해당 요청을 쿼리문으로 변환하여 DB와 연동합니다. 

 

왜 MyBatis에서 JPA로 넘어가나요?

개인적인 생각으로는 MyBatis는 Mapping파일을 경로로 잡는 config파일을 xml로 만들고 또한 Mapper파일을 새로 생성하여 쿼리문을 작성하기때문에 객체지향적인 설계와는 거리가 멀고, 엔티티를 쉽게 사용하려면 별칭으로 등록하고 또한 그마저도 사소한 오타가 존재할 시 오류가 발생합니다. JDBC를 직접 사용하는 것보다는 낫겠지만 그래도 개발시에 상당히 힘들고, 유지보수 역시 하나하나 뒤져보면서 Entity의 값과 name을 비교하는것이 많이 힘듭니다.

 

하지만 JPA는 엔티티에서 그대로 컬럼, 테이블을 지정하고, MVC의 Model부분에서 객체지향적으로 쿼리문을 날리면 작성자의 목적에 맞게 변환시켜 데이터를 CRUD할 수 있게 되어있기 때문에 간편하고, 세팅이나 오류나 발생할 부분이 적어서 확실히 개발 효율을 증가시킬 수 있을 것같습니다.

 

Hibernate(JPA 구현체)

오늘 포스팅에서는 Hibernate라는 JPA 인터페이스의 구현체를 사용할 것입니다. 위 설명대로 JPA는 인터페이스 이기때문에, 작성되어있는 메서드를 구현해야합니다. 이런 것들을 이미 구현해놓은 구현체를 사용함으로서 쉽게 사용할 수 있습니다. 물론 Hibernate말고도 EclipseLink, DataNucleus, OpenJPA, TopLink Essentials등 여러가지가 존재하니, 상황에 맞게 사용하시면 되겠습니다.

 

JPA 연동방법

우선 스프링 부트 프로젝트를 생성해야합니다. 모르시는 분들은 밑의 글을 참고해주세요, 여러 설정중에 JPA 연동과 관련된 라이브러리는 Spring-data-JPA와 사용할 DB의 connector입니다. 참고 Spring-data-JPA만 넣으시면 자동으로 hibernate에 대한 라이브러리도 추가됩니다.

2023.07.14 - [JAVA] - [Spring] Spring boot 프로젝트 생성 방법

 

[Spring] Spring boot 프로젝트 생성 방법

Spring boot란? - Spring Boot란 Spring Framework 프로젝트 생성시 처음하면 매우매우 복잡하고 절대로 쉽게 할 수 없는 초기 설정 및 라이브러리 세팅을 간단하게 만들어주는 프레임워크(FrameWork)입니다. -

lucky-web.tistory.com

Spring Data JPA와 Hibernate에 대한 라이브러리 추가
DB 커넥터 라이브러

 

그 이후 생성된 프로젝트의 외부 라이브러리를 확인하면, hibernate와 JPA에 대한 라이브러리를 확인할 수 있습니다.

hibernate관련 라이브러리
Spring Data JPA 관련 라이브러리

 

외부 라이브러리를 확인하셨다면 src/resources 디렉터리 밑에 application.properties파일을 생성하고 해당 내용을 작성합니다.

application.properties추가

 

application.properties 내용

하나씩 보시면 server.port는 연결할 서버의 포트, url은 jdbc와 커넥션할 DB 스키마의 주소(JDBC에 사용하는 url이나 Mybatis에서 설정해놓은 url과 같습니다.) 유저 아이디와 비밀번호, 그리고 연결할 때 사용하는 드라이버 주소까지 입력합니다.

 

그리고 그 밑은 어떤 DB를 사용하는지 지정하는 부분이고, Database-platform역시 같습니다.

 

3번째는 어떤 단계의 로그부터 남길지를 정하는 단계로, log4j의 여러단계에서 용도에 맞게 지정하시면됩니다.

 

이런 설정들은 더 많이 있지만 필요할 때 마다 알아보시면서 추가하시면 좋을 것같습니다.

 

 

 

 

이제는 엔티티(Entity)와 DB 테이블을 연동하겠습니다. 우선 가상의 테이블을 만들겠습니다.

가상의 테이블

member테이블은 pid,username,name 총 3가지의 컬럼을 가지고 있는 테이블입니다. 해당 테이블을 연결하는 엔티티는 당연히 컬럼의 갯수에 맞게 만들어야겠죠?

@Getter // lombok
@Builder // lombok
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity(name="member")// 테이블 명 작성
public class MemberEntity {

    @Id // pk
    @GeneratedValue(strategy = GenerationType.IDENTITY) // == 시퀀스
    private long pid;

    @Column(nullable = false,unique = true,length = 30) // 속성값 정하기
    private String username;

    @Column(nullable = false, length = 100)
    private String name;

    public MemberEntity(String username, String name) {
        this.username = username;
        this.name = name;
    }
}

테이블 member를 바라보는 MemberEntity클래스를 생성했습니다. @Entity(name = "member")어노테이션은 연결된 DB의 member라는 이름을 가진 테이블과 연동한다는 뜻입니다.

- @Id는 해당 컬럼이 pk라는 것을 의미합니다.

- @GeneratedValue(strategy = GenerationType.IDENTITY)는 MySQL의 auto_increment나 Oracle의 sequence와 같이 자동 숫자 증가를 나타내게 하는 어노테이션인데, GenerationType을 바꿈에 따라 여러가지로 조정할 수 있습니다.

- @Column은 테이블의 컬럼이라는 뜻을 나타내고, 컬럼의 여러가지 속성을 제어할 수 있습니다.

 

이제 JPA의 기능을 사용하기 위한 준비를 하겠습니다.

 

JPARepository생성

 

 

Interface생성

JPA를 끌어올 인터페이스를 생성하고, JPARepository를 상속받습니다.

package com.example.demo.repo;

import com.example.demo.entity.MemberEntity;
import org.springframework.data.jpa.repository.JpaRepository;


public interface MemberRepository extends JpaRepository<MemberEntity, Long> {

}

따로 입력하시지 않아도 됩니다. 그저 JPA의 기능을 끌어쓰기 위한 인터페이스이기때문입니다.

 

 

JPA 작동

 

이제 JPA를 사용하기만 하면됩니다. 보통은 Service에 구현하여 데이터를 가져오고 원하는 방식으로 수정하기도 하지만, 지금은 작동을 보여드리기위하여 Controller에 바로 JPARepository의 의존성을 주입하고 사용해보겠습니다.

 

Controller

package com.example.demo.controller;

import com.example.demo.entity.MemberEntity;
import com.example.demo.repo.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController// @ResponseBody + @Controller
@RequiredArgsConstructor // final 객체를 Constructor Injection해줌.( like @Autowired)
@RequestMapping("/v1")
public class MemberController {
    private final MemberRepository repository;
    /*
    * 멤버조회
    * @return
    * */

    @GetMapping("member")
    public List<MemberEntity> findAllMember(){
        return repository.findAll();
    }

    /**
     * 회원가입
     *
     * @return
     */
    @PostMapping("member")
    public MemberEntity signUp() {
        final MemberEntity member = MemberEntity.builder().username("test_user@gmail.com")
                                                          .name("test user")
                                                          .build();
        return repository.save(member);
    }
}

코드를 보시면 방금 생성한 MemberRepository의 의존성을 주입하고, JPA에서 findAll이라는 함수를 사용하여 해당 값을 responseBody에 return하도록 되어있습니다.

findAll함수를 사용하면 어떤 쿼리문이 작동될까요?

우선 인터페이스 코드를 다시보면...

package com.example.demo.repo;

import com.example.demo.entity.MemberEntity;
import org.springframework.data.jpa.repository.JpaRepository;


public interface MemberRepository extends JpaRepository<MemberEntity, Long> {

}

MemberEntity를 JpaRepository에 담음으로서 해당 인터페이스는 member테이블을 바라보게 되어있습니다.

findAll은 해당 테이블의 모든 데이터를 조회하기때문에

select

          *

from

          member;

쿼리문이 실행되는 것입니다.

그럼 현재 DB에있는 데이터와 웹에서 리턴받는 데이터가 같은지 확인해보겠습니다.

5개의 데이터가 존재한다.

총 5개의 데이터가 존재하는것을 볼 수 있습니다. 그럼 웹에서 findAll()함수를 사용하는 페이지로 가서 5개가 나오는지 확인해보겠습니다.

 

총 5개가 나오는 것을 볼 수 있습니다. 이렇게 JPA의 세팅과 사용방법에 대해 다뤄보았습니다.

Spring boot란?

- Spring Boot란 Spring Framework 프로젝트 생성시 처음하면 매우매우 복잡하고 절대로 쉽게 할 수 없는 초기 설정 및 라이브러리 세팅을 간단하게 만들어주는 프레임워크(FrameWork)입니다.

 

- 학원에서 STS를 통해 스프링 레거시 프로젝트(Spring Legacy Project)를 할 때 매우 오래걸린 초기세팅이 여기선 단 몇번의 클릭으로 끝나는 것을 보고 많이 놀랐던 것 같습니다. 이제 레거시 프로젝트와 스프링 부트 프로젝트의 세팅을 비교해보겠습니다.

 

Spring Boot 프로젝트 생성

우선 IDE는 스프링 부트(Spring boot)를 다루실 때 많이들 사용하시는 IntelliJ를 기준으로 말씀드리겠습니다.

제가 아는 스프링 부트 생성 방법은 두가지로

- intelliJ에서 직접 스프링 부트 프로젝트 생성하기

- Spring.start.io에서 만들어 IntelliJ에서 임포트하기

입니다. IntelliJ에서 생성하는 방법 먼저 보여드리겠습니다.

우선 프로젝트 새로 만들기에서 프로젝트를 클릭합니다.

프로젝트.. 클릭

그럼 다음 화면이 나타나게 되는데 왼쪽 제너레이터(Generator)에서 Spring Initializr를 누르면 됩니다.

스프링 이니셜라이즈 선택

그러면 해당 화면에서 프로젝트명, 저장 경로, 사용언어 및 빌드툴,JDK버젼을 선택하고 다음을 눌러줍니다.
빌드 툴은 보통 Gradle을 추천드리는데, Maven보다 훨씬 빌드속도가 빠르고 잠시 후 보여드리겠지만 라이브러리 추가시의 가독성 역시 훨씬 뛰어납니다.

각종 옵션 추가

다음을 누르면 아래의 사진 처럼 화면이 나옵니다. 초기에 추가해놓을 옵션들과 부트의 버젼을 선택합니다.

이 부분에서 기본 Spring과 많은 차이가납니다. MVNRepository에서 하나하나 찾고 맞는 버젼에 따라 가져와 입력하는 것이 아닌, 기능만 선택하면 해당 라이브러리를 자동으로 세팅해주는 것입니다.

부트 버젼과 기능 선택

대표적으로 몇가지 말씀드리면 Developer Tools는 개발의 편의성을 위한 툴을 의미합니다. 대표적으로 Lombok은 엔티티등을 작성할 때 어노테이션 하나만으로 수많은 반복코드를 작성하지 않아도 되도록해줍니다.

Web은 말 그대로 Web에 관한 기능들입니다. SpringWeb부터 Spring session등.... 세부적인 것들은 검색하셔서 필요한 기능을 추가하시면 됩니다.

그 이외에도 view단과 서버단을 연결하는 Template Engines, 보안 기능의 Security, 관계형 DB 관련 기능인 SQL등등 필요한 것들을 이 화면에서 추가한 뒤 생성을 누르면 됩니다. 저는 해당 글을 위해 기본적인 것들만 추가한 사진을 보여드리겠습니다.

추가한 기능은 오른쪽 하단에 나옵니다.

보시면 Spring Web과 Lombok, MySQL과 통신할때 사용하는 MySQL Driver그리고 Spring Data JPA등 6개의 기능을 넣었습니다. 그럼 생성해볼까요?

프로젝트가 벌써 생성됬다고?!

보시면 빠르게 프로젝트가 생성되었습니다. 이제 Maven의 Pom.xml과 같은 기능인 build.gradle에서 정상적으로 기능이 추가가 되었는지 확인하겠습니다.

정말로 추가가되다니...

보시면 JPA와 JDBC, SpringWeb,lombok등 제가 추가한 기능들이 모두 추가되어 빌드까지 되어있는 상태를 확인할 수 있습니다. 또한 Gradle은 Maven과 다르게 하나의 기능당 거의 1줄만 사용하고있는데요. 빌드 속도도 물론 빠르지만 가독성도 우수해 기능이 많아져도 비교적 관리가 편할 것입니다.

 

이번엔 Spring.io에서 생성하는 것을 다루겠습니다. import하는 것만 다르기 때문에 빠르게 짚고 넘어가겠습니다.

우선 해당 링크에 접속합니다.

https://start.spring.io/

그러면 아래 사진과 같은 화면이 나옵니다.

부트 버젼, 언어, 빌드툴과 프로젝트 명을 선택한 후 추가할 라이브러리는 Dependencies옆 버튼을 클릭합니다.

 

Dependencies 추가

여기서 IntelliJ에서 추가했던 것처럼 lombok, Spring DevTools등을 추가하신 후

GENERATE 버튼을 클릭하면 해당 프로젝트가 다운됩니다. 이후 다운 받은 파일을 IDE에서 임포트해서 열면 동일하게 생성된 프로젝트를 확인할 수 있습니다.

 

이렇게 오늘은 Spring Boot 프로젝트를 생성하는 법을 다뤄보았는데요, 많이 편리해진건 사실이지만 최근에 부트 프로젝트를 이리저리 건드려보니 귀찮더라도 결국 부딪히면서 Spring이나 JAVA에 대한 이해도를 높인 후 편의기능을 사용하는 것이 맞다는 생각이 듭니다. 이상으로 포스팅을 마치겠습니다.

+ Recent posts