[Spring] 입문_JPA

gayoung·2022년 3월 9일
0

스프링 완전 정복

목록 보기
14/33

JPA

  • 기존의 반복코드, SQL을 JPA가 직접 만들어서 실행
  • 개발 생산성 크게 높일 수 있음
  • jpa는 인터페이스이다 + 구현체로 hibernate사용
  • 자바 진행은 jpa가 하고 구현은 다양한 업체들 중 hibernate를 사용한 것
  • jpa는 객체랑 o(object)r(relation)m(mapping)

1. 코드 작성

[ 환경설정 ]

1. build.gradle파일

//implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
  • spring-boot-starter-data-jpa는 jdbc 관련 라이브러리 포함 -> jdbc삭제

2. resources/application.properties

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
  • show-sql : JPA가 생성하는 SQL출력
  • ddl-auto : JPA는 테이블을 자동으로 생성하는 기능 -> none이면 해당 기능제공X, create면 엔티티정보를 바탕으로 테이블 직접 생성

[ 코드 작성 ]

1. Member Entity

package hello.hellospring.domain;

import javax.persistence.*;

@Entity
public class Member {

    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // GenerationType.IDENTITY : 회원 추가 시 id를 직접 넣는 것이아니라 DB가 알아서 넣어줌
    private Long id;

    @Column(name = "name")
    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;
    }
}
  • @Entity : jpa가 관리하는 entity
  • @Column(name = "name") : DB의 컬럼명 중 name과 mapping됨 -> 만약, 컬럼명이랑 일치하지 않는다면 에러남!
    • 이렇게 매핑하면 에러남

2. JpaMemberRepository

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);  // persist=영구저장-> setId등 모든것을 해줌
        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() {
        List<Member> result = em.createQuery("select m from Member m", Member.class)
                .getResultList();
        return result;
    }
}
  • EntityManager em; : build.gradle에서 data-jpa를 등록했기 때문에 스프링부트가 자동으로 EntityManager 만듦
  • 저장, 조회, 업데이트는 쿼리 짤 필요 없음
  • findById는 id가 내가 선택하는 것이아니라 자동으로 id값을 넣어주기 때문에 em.find(Member.class, id)하면 찾을 수 있음??????????????????
  • findByName의 경우 name은 내가 입력하는 것이기 때문에 String name을 이용해 찾아야하나,,???????????????????
  • findAll() : 객체를 대상으로 쿼리를 날림 -> entity 자체를 select하는 것임 -> .getResultList()를 이용해 list로 뽑아냄

3. MemberService(서비스 계층에 트랜잭션 추가)

@Transactional
public class MemberService {}
  • 서비스 계층에 트랜잭션 추가해야 해당 클래스의 메서드를 실행할 때 transaction 시작하고 메서드 종료하면 transaction 커밋
  • 런타임예외 발생하면 롤백
  • JPA를 통한 모든 데이터 변경(save, update 등)은 트랜잭션 안에서 실행해야 한다.

4. SpringConfig

@Configuration
public class SpringConfig {

    private final DataSource dataSource;
 	private final EntityManager em;
    
 	public SpringConfig(DataSource dataSource, EntityManager em) {
 		this.dataSource = dataSource;
 		this.em = em;
 	}
    
    @Bean
	public MemberRepository memberRepository() {
	// return new MemoryMemberRepository();
	// return new JdbcMemberRepository(dataSource);
	// return new JdbcTemplateMemberRepository(dataSource);
	return new JpaMemberRepository(em);
	}
 }

0개의 댓글