[初心-Spring Boot] JPA

0

초심-spring boot

목록 보기
11/16

1. JPA란?


자바 ORM 기술에 대한 표준 명세로, JAVA에서 제공하는 API이다.
JPA는 기존의 반복 코드는 물론이고, 기본적인 SQL도 JPA가 직접 만들어서 실행해준다.
JPA를 사용하면, SQL과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임을 전환을 할 수 있다.
JPA를 사용하면 개발 생산성을 크게 높일 수 있다.

2. Spring boot JPA 적용


2-1. gradle dependency 추가


build.gradle
	dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
      //=========================add=========================
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
      //=========================add=========================
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	runtimeOnly 'mysql:mysql-connector-java'
}

spring-boot-starter-data-jpa 라이브러리를 추가하면 spring-boot-starter-jdbc는 자동으로 추가가 되기 때문에 build.gradle에 명시를 하지 않아도 된다.

2-2. application.properties 프로퍼티 추가


application.properties
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none

spring.jpa.show-sql jpa

실행 시 콘솔에 sql을 보여주는 지 여부

hibernate.ddl-auto

만약 객체에 해당하는 테이블이 없을 경우 자동으로 생성하는 지에 대한 여부

2-3. DTO에 jpa 매핑


MemberDTO.java
package com.rptp.rptpSpringBoot.model;

import javax.persistence.*;

@Entity(name = "member")
public class MemberDTO {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    //@Column(name="name")
    private String name;

@Entity

jpa에게 해당 클래스를 table로 매핑

@Id

해당 필드를 pk로 인식

@GeneratedValue(strategy = GenerationType.IDENTITY)

입력시 만약 id가 null이라면 자동으로 id에 값 설정

@Column(name="name")

해당 필드를 일반 컬럼으로 지정, 만약 위 처럼 name과 필드명이 같으면 생략 가능

2-4. JpaMemberRepository 작성


JpaMemberRepository.java
package com.rptp.rptpSpringBoot.repository.impliment;

import com.rptp.rptpSpringBoot.model.MemberDTO;
import com.rptp.rptpSpringBoot.repository.MemberRepository;
import org.springframework.stereotype.Repository;

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

@Repository
public class JpaMemberRepository implements MemberRepository {

    private final EntityManager em;

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

    @Override
    public MemberDTO save(MemberDTO memberDTO) {
        em.persist(memberDTO);
        return memberDTO;
    }

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

    @Override
    public Optional<MemberDTO> findByName(String name) {
        List<MemberDTO> result = em.createQuery("select m from member m where m.name = :name", MemberDTO.class)
                .setParameter("name", name)
                .getResultList();
        return result.stream().findAny();
    }

    @Override
    public List<MemberDTO> findAll() {
        return em.createQuery("select m from member m", MemberDTO.class)
                .getResultList();
    }
}

EntityManager

그대로 엔티티를 관리하는 객체이다.
EntityManager를 통해 테이블과 매핑된 엔티티를 실제로 사용하게 된다

em.persist( O )

영속성 컨텍스트를 통해서 엔티티를 영속화 한다

  • 영속성: 데이터를 생성한 프로그램의 실행이 종료되더라도 사라지지 않는 데이터의 특성

em.createQuery

쿼리를 생성한다.
문자열에서 "member"과 매핑되는 것은 DTO에서 설정한 Entity네임이다.
문자열 내 파라미터는 ':'로 입력받는다.

2-5. MemberService 수정


MemberService;
package com.rptp.rptpSpringBoot.service;

import com.rptp.rptpSpringBoot.model.MemberDTO;
import com.rptp.rptpSpringBoot.repository.MemberRepository;
import com.rptp.rptpSpringBoot.repository.impliment.MemoryMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Service
public class MemberService {
    private final MemberRepository memberRepository;

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


    //화원가입
    //================ADD================
    @Transactional
     //================ADD================
    public Long join(MemberDTO memberDTO) {
        // 같은 이름의 있는 중복 회원 x
        validateDuplicateMember(memberDTO);

        memberRepository.save(memberDTO);
        return memberDTO.getId();
    }

    private void validateDuplicateMember(MemberDTO memberDTO) {
        memberRepository.findByName(memberDTO.getName())
                .ifPresent(m -> {
                    throw new IllegalStateException("이미 존재하는 회원입니다");
                });
    }

    //전체 회원 조회
    public List<MemberDTO> findMembers() {
        return memberRepository.findAll();
    }

    // id에 맞는 회원 조회
    public Optional<MemberDTO> findOne(Long memberId) {
        return memberRepository.findById(memberId);
    }
}

@Transactional

DB에서 데이터를 입력, 수정, 삭제 하는 메서드에 달아주는 에너테이션이다.
클래스에도 달 수 있는데, 해당 클래스에 속해있는 모든 메서드가 @Transactional 기능이 생긴다.

2-6. 실행



테스트 코드를 통과하는 것을 볼 수 있다.


회원가입을 하면 성공적으로 입력 되는 것을 볼 수 있다.

콘솔에 어떤 명령어가 입력되었는지도 확인할 수 있다.

3. Data JPA


spring framework에서 JPA를 편리하게 사용할 수 있도록 지원하는 프로젝트

  • CRUD 처리를 위한 공통 인터페이스 제공

  • repository 개발 시 인터페이스만 작성하면 실행 시점에 스프링 데이터 JPA가 구현 객체를 동적으로 생성해서 주입

  • 데이터 접근 계층을 개발할 때 구현 클래스 없이 인터페이스만 작성해도 개발을 완료할 수 있도록 지원

3-1. 기존에 설정한 @Repository 해제


3-2. SpringDataJpaMemberRepository 생성


SpringDataJpaMemberRepository.java
package com.rptp.rptpSpringBoot.repository;

import com.rptp.rptpSpringBoot.model.MemberDTO;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

//JpaRepository을 extend받으면 자동으로 Spring 컨테이너에 Bean으로 알아서 입력됨.
public interface SpringDataJpaMemberRepository extends JpaRepository<MemberDTO, Long> , MemberRepository{

    @Override
    //sql: select m from member m where m.name = ?
    Optional<MemberDTO> findByName(String name);
}

3-3. 실행(...?)





이게되네;;

참조


https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8/lecture/49597
JPA란 https://gmlwjd9405.github.io/2019/08/04/what-is-jpa.html
영속성이란 https://sugerent.tistory.com/587
Spring Data JPA https://data-make.tistory.com/621

0개의 댓글