JPA

황상익·2024년 4월 1일

Spring 입문 

목록 보기
6/7

JPA는 기존 반복 코드는 물론이고, 기본적 SQL도 JPQ가 직접 만들어서 실행
JPA를 사요하면 SQL과 데이터 중심의 설계에서 객체 중심의 설계로 가능

build.gradle 설정

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'
}
}

스프링 부트에 JPA 설정 추가

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

JPA 엔티티 매핑

package hello.hellospring.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

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

    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;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
public class JpaMemberRepository implements MemberRepository {

    private final EntityManager em; //JPA 구동 원리

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

    @Override
    public Member save(Member member) {
        em.persist(member);
        return member; //JPA가 자동으로 쿼리 짠다.
    }

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

    @Override
    public Optional<Member> findByName(String name) {
        List<Member> rst = em.createQuery("select m from Member m where m.name = :name", Member.class)
                .setParameter("name", name).getResultList();
        return rst.stream().findAny(); //findByName으로 하나만 찾아온다
    }

    @Override
    public List<Member> findALl() {
        return em.createQuery("select m from Member", Member.class) //이미 Mapping 되어 있다.
                .getResultList();
    }
}
@Service
@Transactional //data를 저장 변경
public class MemberService {

    //DI
    @Autowired
    private final MemberRepository memberRepository;

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

    public Long join(Member member){
        validateDuplicateMember(member);
        return member.getId();
    }

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

    public List<Member> findMembers(){
        return memberRepository.findALl();
    }

    public Optional<Member> findOne(Long id){
        return memberRepository.findById(id);
    }
}

JPA를 통한 모든 데이터 변경은 Transaction 안에서 실행

@Configuration
public class SpringConfig {

    //spring Jpa가 interface에 대한 구현체를 찾도록 만든다0
    private final MemberRepository memberRepository;

    public SpringConfig(MemberRepository memberRepository) {
        this.memberRepository = memberRepository; //jpa 구현체 만들어 놓은거 등록
    }

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository); //memberService에 의존관계 setting
    }

    /*
    interface를 보고 springBean 자동 등록
    -> proxt라는 기술로 객체를 생성 -> springBean 생성 -> inject
     */
}

스프링 데이터 JPA
스프링 부트와 JPA만 사용해도 개발 생산성 증가, 개발 코드 감소
여기에 스프링 데이터 JPA 사용시, 리포지토리에 구현 클래스 X, 인터페이스만 갖고 개발 완료. CRUD 기능도 스프링 데이터 JPA가 모두 제공

package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

//spring data Jpa가 spring Bean을 자동으로 등록
public interface SpringDataJapMemberRepository extends JpaRepository<Member, Long>, MemberRepository {
    @Override
    Optional<Member> findByName(String name);
}

스프링 데이터 JPA 제공 기능
1. 인터페이스를 통한 기본적인 CRUD
2. 페이징 기능 자동 제공

profile
개발자를 향해 가는 중입니다~! 항상 겸손

0개의 댓글