본문 바로가기
Spring Framework/JPA

스프링부트 JPA CRUD 사용방법 정리(MySQL, Gradle)

by wakestand 2021. 11. 5.
반응형

 

GitHub - wakeisle9933/jpa-example: JPA 예제

JPA 예제. Contribute to wakeisle9933/jpa-example development by creating an account on GitHub.

github.com

해당 글은 위와 같이 세팅을 한 뒤에 작성한 내용인데

동일한 코드로 따라한다고 해도

자바 버전이 다르거나 혹은 Lombok이 없어서

동일하게 동작하지 않을 수 있기 때문에

 

세팅을 동일하게 맞춰줘야 하고

아니면 위 github 링크로 들어가서

내가 작성해놓은 예제가 있으니

 

인텔리제이 Github 연결방법 정리(로컬 -> 깃/ 깃 -> 로컬)

인텔리제이(IntelliJ) 에서 깃허브와 연동하려고 할 때 깃허브 Repository에 내 프로젝트를 넣는 방법 깃허브 Repository 안의 프로젝트를 내 인텔리제이로 가져오는 방법 두 가지를 차례대로 수행해보

wakestand.tistory.com

이걸 Local 서버로 옮겨온 다음

똑같이 따라하면서 확인해줘도 된다

(처음부터 만들어보고 싶으면 empty branch로 전환해서

origin branch를 따라 만들어보면 됨)

 

스프링부트 JPA MySQL 연결방법 정리(Gradle)

스프링부트에서 MySQL을 이용해서 JPA를 사용하려고 하는 경우 (Gradle) build.gradle 파일과 application.properties 파일을 변경해줘야 하는데 먼저 build.gradle의 경우에는 dependencies 에 JPA와 MySQL 옵션..

wakestand.tistory.com

먼저 MySQL 설정을 마치고 JPA를 연결한 다음

 

JPA를 간단히 알아보자면

Controller / Entity / Repository로 나뉘는데

 

Controller > 자바 로직 수행

Entity > 테이블 정보 설정

Repository > 쿼리 정보 설정

 

외부에서 Controller를 호출하면

Repository가 Entity를 가지고 처리를 한 후에

반환하는 구조라고 보면 된다

 

예제에서는 로컬 서버에서

GET 방식으로 Controller를 호출하면

CRUD를 수행하는 식의 예제를 진행해보자

 

먼저 Entity와 Repository 부터 만들어 보자면

 

Entity (테이블 정보 설정)

 

lombok을 사용하고 있기 때문에

매우 간단하게 Entity를 만들 수 있는데

일단 전체 코드는 아래와 같고

 

package com.jpa.jpaexample.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Entity(name="sample_member")
public class CrudEntity {

    @Id
    @Column(nullable = false, unique = true)
    private String name;

    @Column(nullable = false)
    private int age;

}

 

SQL 사용 시 파라미터에 값을

쉽게 넣어주기 위한 어노테이션인

@Builder

객체의 값 확인을 위한

@ToString

생성자를 자동 완성시켜주는

@AllArgsConstructor

@NoArgsConstructor

을 클래스 위에 넣어주자 (Lombok 필요)

 

마지막으로 @Entity에

해당 class에 지정할 테이블명을 입력하고

(MySQL에 테이블 생성해 두어야 함!!)

 

테이블에 들어있는 컬럼을 Entity 클래스 안에 넣어주자

여기서 @Id 어노테이션이 무조건 들어가야 하기 때문에

PK에 해당하는 컬럼에 @Id를 넣어주면 된다

 

이것만 해주면 Entity 설정은 간단히 끝이 난다

 

다음은 Repository 인데

이건 더 간단하다

 

Repository (쿼리 정보 설정)

 

import com.jpa.jpaexample.entity.CrudEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface CrudEntityRepository extends JpaRepository<CrudEntity, String> {

    @Query(value = "select name, age from sample_member where name = :name", nativeQuery=true)
    List<CrudEntity> searchParamRepo(@Param("name") String name);

}

 

Repository의 경우에는

JpaRepository를 extends 받으면

해당 Repository로 JPA의

대부분의 자동 쿼리 기능을 수행할 수 있고

 

해당 클래스 안에 메소드를 선언하고

위에 @Query를 넣어주면

JPA에서 커스텀 쿼리를 사용할 수 있게 된다

파라미터는 :name 과 같이 :를 앞에 붙이는 것으로

파라미터를 지정 가능하고

 

메소드 호출 시

@Param("파라미터") 데이터타입 데이터명

이런 방식으로 파라미터를 받아 사용할 수 있다

 

이제 Entity와 Repository를 만들었으니

Controller에서 사용하는 방법인데

 

Controller (자바 로직 수행)

 

이제 Controller에서 CRUD를 수행해볼 순간인데

전체 조회 / 파라미터를 사용한 조회 / INSERT / UPDATE / DELETE

를 차례대로 수행해보자

(쿼리 복붙 시에는 글 맨 아래 참고)

 

먼저 Controller 상단에

@RestController

@RequiredArgsConstructor

@RequestMapping("/localhost에서 접속 시 뭐로 구분할건지")

> localhost:8080/test 이런 식으로 사용하게 됨

을 넣어주고 아까 생성한 Repository를 끌어온다

 

전체 조회

 

메소드를 작성한 뒤에 상단에

@GetMapping("값"); 을 넣어주는데

해당 메소드는

localhost:8080/test/search

이런 방식으로 호출하게 된다

 

전체 조회는 매우 간단하게도

Repository.findAll();

만 해주면 끝이 난다

(toString() 은 반환형태가 String이어서 사용)

 

MyBatis의 경우에는

Controller > Service > Impl > Dao > Mapper

의 5단 구조로 조회를 하는 걸 생각해보면 

JPA에서 단순 반복 쿼리는 매우 쉽게 사용이 가능하다

 

파라미터를 사용한 조회

 

EntityManager를 사용해서 쿼리를 만들어 사용하는 방법

Repository에서 만들어둔 쿼리를 끌어오는 방법

이렇게 두 방법이 있는데 차례대로 설명한다

 

먼저 EntityManager를 사용할 경우에는

Controller에서 EntityManager를 가져온 뒤

 

.createQuery로 쿼리를 생성하고

파라미터는 쿼리 안에

:파라미터명 으로 지정해준다

 

그리고 설정한 파라미터는

.setParameter("파라미터명", 들어갈_값)

으로 지정해줄 수 있다

마지막으로 .getResultList(); 를 사용해

조회된 값을 뽑아온다

 

다음으로 Repository에

쿼리를 만들어 두었을 경우에는

repository.작성한메소드명(파라미터);

로 쉽게 파라미터를 넣고 조회가 가능하다

 

INSERT

 

Entity를 선언한 후

(Entity에 테이블 정보가 있음)

 

Entity명.builder() 를 사용해서

파라미터를 넣어줄 수 있는데 .name(name)

이면 name 컬럼에 호출하면서 파라미터로 받은

name을 넣어준다는 얘기다

 

파라미터를 넣어준 후 .build() 를 써서

완성해주면 되는데

 

저장 자체는

Repository.save(Entity명);

을 해주면 파라미터로 넣은 값이 바로 INSERT가 되고

동일한 값을 넣고 다시 repository.save() 호출하면

동일한 PK를 대상으로 UPDATE를 수행한다

 

위 예제에서는 INSERT만 보여주려고 하기 때문에

메소드 호출 시 findById(파라미터).isPresent();

를 사용해서 테이블에 해당하는 키가 있으면

save를 하지 않는 식으로 INSERT를 구현했다

 

UPDATE

 

repository.save(Entity명) 메소드를 사용할 경우

Key에 해당하는 값이 없을 경우 INSERT

있을 경우에는 UPDATE를 수행하게 되는데

 

위 INSERT와 비교해보면

값이 존재하지 않을 경우에

Return 처리하는 것을 제외하면

방법은 똑같다고 보면 된다 

 

DELETE

 

repository.delete(Entity명);

을 사용해주면 간단히 삭제가 가능하다

 

위 예제에서는 delete 할 값이 없을 경우에

return 메시지를 다르게 보내려고

if 문을 추가하였는데

 

단순하게 보자면

repository.delete(entity) 를 해도

정상적으로 작동한다


JPA CRUD 테스트를 진행하다가 막힐 경우에는

내가 글 맨 상단에 링크한 github에

환경설정 세팅부터 실제 어떻게 호출하는지까지

다 입력해 놓은것이 있기 때문에 이걸 참고해주면

훨씬 쉽게 이해할 수 있을 것으로 본다

 

마지막으로 Controller 에서 사용한 코드는 아래와 같다

 

import com.jpa.jpaexample.entity.CrudEntity;
import com.jpa.jpaexample.repository.CrudEntityRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

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

@RestController
@RequiredArgsConstructor
@RequestMapping("/test")
public class CrudController {

    private final CrudEntityRepository crudEntityRepository;

    @PersistenceContext
    private EntityManager entityManager;

    @GetMapping("update")
    public String updateMember(@RequestParam(value = "name") String name, @RequestParam(value = "age") int age) {
        if(crudEntityRepository.findById(name).isEmpty()) { // 값 존재여부 확인
            return "입력한 " + name + "이 존재하지 않습니다";
        } else {
            crudEntityRepository.save(CrudEntity.builder().name(name).age(age).build());
            return name + "의 나이를 " + age + "로 변경 완료";
        }
    }

    @GetMapping("delete")
    public String deleteMember(@RequestParam(value = "name") String name) {
        if(crudEntityRepository.findById(name).isEmpty()) { // 값 존재여부 확인
            return "입력한 " + name + "이 존재하지 않습니다";
        } else {
            crudEntityRepository.delete(CrudEntity entity = CrudEntity.builder().name(name).build());
            return name + " 삭제 완료";
        }
    }

    @GetMapping("insert")
    public String insertMember(@RequestParam(value = "name") String name, @RequestParam(value = "age") int age) {
        if(crudEntityRepository.findById(name).isPresent()) {
            return "동일한 이름이 이미 있습니다";
        } else {
            CrudEntity entity = CrudEntity.builder().name(name).age(age).build();
            crudEntityRepository.save(entity);
            return "이름 : " + name + " 나이 : " + age + "으로 추가 되었습니다";
        }
    }

    @GetMapping("search")
    public String searchAllMember() {
        return crudEntityRepository.findAll().toString();
    }

    @GetMapping("searchParam")
    public String searchParamMember(@RequestParam(value = "age") int age) {
        List resultList = entityManager.createQuery("select name from sample_member where age > :age")
                                       .setParameter("age", age)
                                       .getResultList();
        return resultList.toString();
    }

    @GetMapping("searchParamRepo")
    public String searchParamRepoMember(@RequestParam(value = "name") String name) {
        return crudEntityRepository.searchParamRepo(name).toString();
    }

}
반응형

댓글