FireDrago

[Spring Data JPA] 스프링 데이터 JPA 사용하기 본문

프로그래밍/JPA

[Spring Data JPA] 스프링 데이터 JPA 사용하기

화이용 2024. 4. 23. 12:50

스프링 데이터 JPA는 JPA를 편리하게 사용할 수 있도록 여러 기능들을 제공한다.

 

그 중 하나가 Repository 구현 클래스를 스프링 데이터 JPA가 생성하는 기능이다.

인터페이스만 있다면, 기본적인 CRUD 기능을 가진 Repository  구현체를 스프링 데이터 JPA가 자동으로 생성한다.

코드로 알아보자

 

<Entity>

@Entity
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "username", "age"})
public class Member {

    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;
    private String username;
    private int age;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;

    public Member(String username) {
        this(username, 0);
    }

    public Member(String username, int age) {
        this(username, age, null);
    }

    public Member(String username, int age, Team team) {
        this.username = username;
        this.age = age;
        if (team != null) {
            changeTeam(team);
        }
    }
	
    // 관계 설정 메서드 (연관관계 주인에게 만들자)
    private void changeTeam(Team team) {
        this.team = team;
        team.getMembers().add(this);
    }
}

 

@Entity
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "name"})
public class Team {

    @Id
    @GeneratedValue
    @Column(name = "team_id")
    private Long id;

    private String name;

    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();

    public Team(String name) {
        this.name = name;
    }
}

 

Member 와 Team 엔티티를 만들었다. Member 가 연관관계의 주인이고, 다대일 관계이므로 지연로딩을 설정했다.

Team 에도 일대다 양방향 관계를 설정했다.

 

이제 스프링 데이터 JPA를 사용하기 위해 인터페이스를 만들어보자

놀랍게도 인터페이스만 만들어도, MemberRepository 를 통해서 기본 CRUD 기능을 전부 사용할 수 있다.

// JpaRepository<엔티티, id 타입> 상속
public interface MemberRepository extends JpaRepository<Member, Long> {
}

 

 

JpaRepository는 대부분의 공통 메서드를 제공한다.

JpaRepository <Entity, id 타입> 을 상속 받으면 스프링 데이터 JPA가 프록시 객체로 구현클래스를 생성한다.

JpaRepository 공통메서드
save(S) 새로운 엔티티는 저장하고 이미 있는 엔티티는 병합한다.
delete(T) 엔티티 하나를 삭제한다. 내부에서 EntityManager.remove() 호출
findById(ID) 엔티티 하나를 조회한다. 내부에서 EntityManaber.find() 호출
getOne(ID) 엔티티를 프록시로 조회한다. 내부에서 EntityManager.getReference() 호출
findAll(...) 모든 엔티티를 조회한다. 정렬(Sort)나 페이징 (Pageable) 조건을 파라미터로 제공할 수 있다.

 

@SpringBootTest
@Transactional
public class MemberRepositoryTest {

    @Autowired
    MemberRepository memberRepository;
    @Autowired
    TeamRepository teamRepository;

    @Test
    public void basicCRUD() {
        Member member1 = new Member("member1");
        Member member2 = new Member("member2");
        memberRepository.save(member1);
        memberRepository.save(member2);

        //단건 조회 검증
        Member findMember1 =
                memberRepository.findById(member1.getId()).get();
        Member findMember2 =
                memberRepository.findById(member2.getId()).get();

        assertThat(findMember1).isEqualTo(member1);
        assertThat(findMember2).isEqualTo(member2);

        //리스트 조회 검증
        List<Member> all = memberRepository.findAll();
        assertThat(all.size()).isEqualTo(2);

        //카운트 검증
        long count = memberRepository.count();
        assertThat(count).isEqualTo(2);

        //삭제 검증
        memberRepository.delete(member1);
        memberRepository.delete(member2);

        long deletedCount = memberRepository.count();
        assertThat(deletedCount).isEqualTo(0);
    }
}

 

테스트 코드를 실행하면 , CRUD 기능이 잘 작동하는 것을 확인할 수 있다.

'프로그래밍 > JPA' 카테고리의 다른 글

[JPA] cascade는 언제 사용해야 할까?  (0) 2024.04.09
[JPA] @PersistenceContext 사용해야 하는 이유  (0) 2024.04.08
[JPA] JPQL 기본문법 2  (0) 2024.04.06
[JPA] JPQL 기본문법 1  (0) 2024.04.04
[JPA] 연관관계 관리  (0) 2024.04.01