JAVA-JIKIMI / JPA

jpa 완벽 뽀개기
0 stars 0 forks source link

[실습 코드 릴레이] 박효원 4주차 #37

Open lsucret opened 2 years ago

lsucret commented 2 years ago

애플리케이션 구현 준비

구현 요구사항

그동안은 데이터적인 설계. 그래서 이번엔 뭘 어디까지 구현할 건지를 전체적으로 설명

구현

회원 기능

상품 기능

주문 기능

제외

애플리케이션 아키텍처

image

계층형 구조 사용

개발 순서: 서비스, 리포지토리 계층을 개발하고, 테스트 케이스를 작성해서 검증, 마지막에 웹 계층 적용

회원 도메인 개발

목차

회원 리포지토리 개발 회원 서비스 개발 회원 기능 테스트

회원 리포지토리 개발

@Repository 이 어노테이션을 클릭해 들어가면 @Component가 있다. spring boot는 @SpringBootApplication 붙은 애 패키지랑 이 패키지 하위에 있는 애를 Component scanning 함. 그래서 spring bean으로 자동 등록.

@PersistenceContext spring이 엔티티매니저를 주입해줌 순수 JPA만 쓰면 엔티티매니저 팩토리에서 엔티티 매니저 꺼내 써야하는데, 스프링이 그걸 다 해줌. 엔티티매니저 팩토리를 직접 주입하고 싶다면?

@PersistenceUnit
private EntityManagerFactory emf;

JPA가 save를 하면 영속성 컨텍스트에 member를 올린다.

그 때에 키는 @id값이고 나머지가 밸류.

그리고 id 멤버변수에 값을 채워줌. 아직 DB에 값이 들어가지 않은 상황에서도.

javax.Transactional 과 spring Transactional

Transactional

@Transactional(readOnly = true)

@Transactional

@Transactional 어노테이션 인식 우선순위

디펜던시 주입

setter injection

@Autowired // setter injection
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}

생성자 injection

private final MemberRepository memberRepository;

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

더 간단하게

private final MemberRepository memberRepository;

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

@Autowired 가 없어도 최신 버전 스프링은 생성자가 하나만 있을 경우 자동 autowired 해줌. final도 붙여줌.

롬복 사용


회원 서비스 개발

소스에서 확인


회원 기능 테스트

테스트 요구사항

junit 4 -> 5 jupiter로의 변화

(4에선) @RunWith(SpringRunner.class) 를 쓰지만

(5에선) @ExtendWith(SpringExtension.class) 를 사용

그런데 @SpringBootTest 어노테이션에 @ExtendWith(SpringExtension.class) 가 이미 들어가있어서 생략 가능하다!

(@RunWith가 더이상 보이지 않는 이유)[https://www.whiteship.me/springboot-no-more-runwith/]

  1. 롤백되지 않도록 세팅 @Rollback(false)를 테스트 메서드 위에 붙여줌

        @Test
        @Rollback(false)
        public void 회원가입() throws Exception {
  2. 롤백은 되야 하지만 insert 쿼리가 날아가는건 보고 싶음

    @Autowired
    EntityManager em;

    @Test
    public void 회원가입() throws Exception {
        // given
        Member member = new Member();
        member.setName("kim");

        // when
        Long savedId = memberService.join(member);

        // then
        em.flush(); // insert 쿼리를 보고 싶을 때 사용
        assertEquals(member, memberRepository.findOne(savedId));

    }

cheat sheet

테스트 코드를 더 편하게 돌리는 법.

spring:
  datasource:
    url: jdbc:h2:mem:testdb # in memory mode로 동작

DB 띄울 필요 없이 반복적으로 테스트 코드 실행 가능하다. (링크)[http://h2database.com/html/cheatSheet.html]

그런데, spring boot 는 test 코드에 application.yml 에 뭘 따로 적지 않아도 알아서 인메모리 DB로 돌려준다.

lsucret commented 2 years ago

다음은 @Component를 사용해 만든 어노테이션이 @Component와 다른 점이 무엇인지를 정리하였습니다.

@Repository

@Repository는 Exception translation을 활성화시켜 준다. spring이 지원하지 않는 Exception을 관련된 Translator 인스턴스를 활용해서 spring이 지원하는 Exception 계층으로 변환해준다. @Repository는 이 exception translation 기능을 활성화시키는 역할을 한다.

다음은 spring Data JPA에서 @Repository를 활용해 exception translation을 해준 예이다.

https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa (4.1. Exception Translation Is Alive and Well 번역) 질문. spring data JPA에서는 올드한 ORM 템플릿(JpaTemplate, HibernateTemplate. spring 5 에서는 이 템플릿들이 삭제되었다.)들에 의존하지 않는다. 그럼에도 불구하고 JPA 익셉션이 spring의 DataAccessException 계층에 맞게 변환이(exception translation) 될까? 답은, 물론이다. Exception Translation은 DAO의 @Repository 어노테이션을 붙여줌으로써 여전히 동작한다. 이 어노테이션을 사용하면 spring bean postprocessor 가 컨테이너에서 발견된 모든 PersistenceExceptionTranslator 인스턴스를 사용하여 모든 @Repository 빈에 advice하고 이전과 마찬가지로 exception translation을 제공할 수 있습니다.

@Service

아직 추가적인 기능은 없다.

@Controller

@RequestMapping 어노테이션을 해당 어노테이션 밑에서만 사용할 수 있다.

lsucret commented 2 years ago

@transactional(readOnly = true) 에서 나온 더티체킹이란?

Dirty란 상태의 변화가 생긴 정도로 이해하시면 됩니다. 즉, Dirty Checking이란 상태 변경 검사 입니다.

JPA에서는 트랜잭션이 끝나는 시점에 변화가 있는 모든 엔티티 객체를 데이터베이스에 자동으로 반영해줍니다.

이때 변화가 있다의 기준은 최초 조회 상태입니다.

JPA에서는 엔티티를 조회하면 해당 엔티티의 조회 상태 그대로 스냅샷을 만들어놓습니다. 그리고 트랜잭션이 끝나는 시점에는 이 스냅샷과 비교해서 다른점이 있다면 Update Query를 데이터베이스로 전달합니다.

https://jojoldu.tistory.com/415