Skip to content

JPA Section 3‐4

SH-Seol edited this page May 25, 2024 · 3 revisions

애플리케이션 구현 준비

요구사항을 분석

핵심 비즈니스 구현에 초점

애플리케이션 아키텍처

Untitled

계층형 구조 사용

  • controller, web: 웹 계층
  • service: 비즈니스 로직, 트랜잭션 처리
  • repository: JPA를 직접 사용하는 계층, 엔티티 매니저 사용
  • domain: 엔티티가 모여 있는 계층, 모든 계층에서 사용
package jpabook.jpashop.repository;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jpabook.jpashop.domain.Member;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public class MemberRepository {

    @PersistenceContext
    private EntityManager em;

    public void save(Member member){
        em.persist(member);
    }

    public Member findOne(Long id){
        return em.find(Member.class, id);
    }

    public List<Member> findAll(){
        return em.createQuery("select m from Member m", Member.class).getResultList();
    }
}
  • @Repository로 인해 자동으로 spring bean으로 등록
  • @PersistenceContext, EntityManager를 하면 spring이 em을 만들어서 주입해준다.
  • sql은 table을 대상으로 query, but jpql은 entity 대상으로 query
@Transactional(readOnly = true)
    public List<Member> findMembers(){
        return memberRepository.findAll();
    }
  • 읽기에는 readOnly = true로 하는 것이 성능 면에서 더 좋다.
  • default는 readOnly = false
private void validateDuplicateMember(Member member) {
        //Exception
        List<Member> findMembers = memberRepository.findByName(member.getName());
        if(!findMembers.isEmpty()){
            throw new IllegalStateException("이미 존재하는 회원입니다.");
        }
    }
  • 실무에서는 같은 이름이 동시에 들어오면 둘 다 문제 없이 넘어가기에 유니크 제약 조건을 걸어야 한다.

유니크 제약조건

/**** 1번 방식 *****/
@Entity()
@Table(name="Member", uniqueConstraints = {
        @UniqueConstraint(
                name="NAME_AGE_UNIQUE",
                columnNames={"NAME","AGE"}
        )})
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;    //이걸 왜 Wrapper자료형으로 잡을까?

    private String name;
    private String phone;
    }

/**** 2번 방식 *****/
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;    //이걸 왜 Wrapper자료형으로 잡을까?

    @Column(name="name",unique = true) //실행에는 영향을 주지 않는다. 단지 DDL생성에만 관여할 뿐이다.
    private String name;

    @Column(name="phone",unique = true)
    private String phone;
    }
   

.

@AllArgsConsturctor : 모든 것에 생성자

@RequiredArgsConstructor: final이 붙은 것만 생성자

@Transactional이 test code에 붙으면 기본적으로 rollback해버림.

이 상태로 insert query를 하면 db에 넣지 않음.

Clone this wiki locally