본문 바로가기
프로그래밍

15. [JPA] Spring Data JPA

by 탁구치는 개발자 2017. 12. 14.

Spring Data 프로젝트 하위에 Spring Data JPA가 존재

JPA를 쉽게 사용할 수 있도록 제공해 주는 프로젝트이다.


"쉽게 사용할 수 있다" 의미?

대게 DB관련 로직이 있는 데이터 계층에 select, insert, update, delete와 같은 코드를 반복적으로 작성한다.

Spring Data JPA에서는 이런 지루하고 반복적인 작업을 인터페이스 선언만으로 해결하였다.


JpaRepository 인터페이스를 상속하면 된다. 

인터페이스만 선언해서 어떻게 해결했지? 라는 의문점이 들 수 있을 것이다. Spring Data JPA에서는 런타임 시점에 구현 객체를 동적으로 생성해준다. (JDK Dynamic Proxy 이용)

1
2
public interface SDTRepository extends JpaRepository<SpringDataMember, Integer> {
}
cs


테스트 해보자.

 - 전체 삭제 테스트

 - total count 테스트

 - custom repository 테스트

 - native query 테스트

 - 페이징 테스트


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
@Slf4j
@Transactional
@RunWith(SpringRunner.class)
@SpringBootTest
@EnableAsync
public class SpringDataJPATest {
 
    public static final int CNT = 200;
 
    @Autowired
    private MemberRepository memberRepository;
 
    // 테스트 데이터
    @Before
    public void before() {
        for (int i = 0; i < CNT; i++) {
            SpringMember member = new SpringMember(i, "Lee" + i);
            memberRepository.save(member);
        }
 
        memberRepository.flush();
    }
   
    @Test
    public void 전체삭제() {
        memberRepository.deleteAll();
        memberRepository.flush();
 
        SpringMember entityMember = memberRepository.findOne(5);
        assertNull(entityMember);
    }
    
    @Test
    public void testTotalCnt() {
        List<SpringMember> list = memberRepository.findAll();
        assertThat(list.size(), is(CNT));
        assertThat(memberRepository.count(), is(Long.valueOf(CNT)));
    }
    
    @Test
    public void 커스텀메서드테스트() {
        assertThat(3, is(memberRepository.findTop3ByNameLike("Lee%").size()));
        assertThat(Long.valueOf(CNT), is(memberRepository.countByNameLike("Lee%")));
    }   
 
    @Test
    public void testNativeQuery() {
        List<SpringMember> list = memberRepository.nativeQuery();
        assertThat(list.size(), is(CNT));
 
        SpringMember member = memberRepository.nativeQueryByName("Lee0");
        assertThat(member.getName(), is("Lee0"));
    }
 
    @Test
    public void testPaging() {
        Page<SpringMember> page = memberRepository.findAll(new PageRequest(315));
        System.out.println("=======================================================");
        System.out.println("page : " + page);
        System.out.println("totalElements : " + page.getTotalElements());
        System.out.println("totalPages : " + page.getTotalPages());
        System.out.println("nextPage : " + page.nextPageable());
        System.out.println("previousPage : " + page.previousPageable());
        System.out.println("=======================================================");
    }
}
 
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "SPRING_DATA_MEMBER")
@Entity
public class SpringMember {
 
    @Id
    private int seq;
    private String name;
}
 
public interface MemberRepository extends JpaRepository<SpringMember, Integer> {
 
    SpringMember findBySeqAndName(int seq, String name);
 
    List<SpringMember> findTop3ByNameLike(String name);
 
    SpringMember readBySeq(int seq);
 
    SpringMember readByName(String name);
 
    SpringMember queryBySeq(int seq);
 
    long countByNameLike(String name);
 
    long countByName(String name);
 
    @Query(value = "SELECT seq, name FROM SPRING_DATA_MEMBER", nativeQuery = true)
    List<SpringMember> nativeQuery();
 
    @Query(value = "SELECT seq, name FROM SPRING_DATA_MEMBER WHERE name = :name", nativeQuery = true)
    SpringMember nativeQueryByName(@Param(value = "name"String name);
 
    @Async
    CompletableFuture<List<SpringMember>> readAllBy();
}
cs