Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 서버설정
- 자료구조와 함께 배우는 알고리즘 입문
- Kernighan의 C언어 프로그래밍
- 코드로배우는스프링웹프로젝트
- 처음 만나는 AI수학 with Python
- 선형대수
- 네트워크 설정
- /etc/network/interfaces
- 친절한SQL튜닝
- network configuration
- GIT
- ㅒ
- 코드로배우는스프링부트웹프로젝트
- 구멍가게코딩단
- 자바편
- 스프링 시큐리티
- 스프링부트핵심가이드
- 리눅스
- resttemplate
- 알파회계
- 페이징
- 티스토리 쿠키 삭제
- iterator
- d
- baeldung
- 처음 만나는 AI 수학 with Python
- 데비안
- 자료구조와함께배우는알고리즘입문
- 이터레이터
- 목록처리
Archives
- Today
- Total
bright jazz music
JpaRepository + 페이징, 쿼리메소드 본문
package org.zerok.ex2.repository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.test.annotation.Commit;
import org.zerok.ex2.entity.Memo;
import javax.transaction.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.stream.IntStream;
@SpringBootTest
public class MemoRepositoryTests {
@Autowired
MemoRepository memoRepository;
@Test
public void testClass(){
System.out.println(memoRepository.getClass().getName());
/*
* testClass()메서드는 MemoRepository 인터페이스 타입의 실제 객체가 어떤 것인지 확인한다.
* 스프링이 내부적으로 해당 클래스를 자동생성(AOP)하는데, 이 때 선언한 적 없는 클래스의 이름이
* com.sun.proxy.$Proxy110 와 같이 콘솔에 출력된다.(동적 프록시 방식으로 생성됨)
*
*
* */
}
@Test //등록작업 테스트
public void testInsertDummies(){
IntStream.rangeClosed(1,100).forEach(i -> {
Memo memo = Memo.builder().memoText("Sample..." + i).build();
memoRepository.save(memo);
});
//한 번에 여러 개의 객체를 저장하도록 작성. 100개의 Memo 객체를 생성하고 MemoRepository를 이용해서 insert.
// 두 번 실행하면 테이블에 행이 200번까지 만들어진다.
}
@Test //조회작업 테스트: findById()사용
public void testSelect(){
//DB에 존재하는 mno
Long mno = 100L;
Optional<Memo> result = memoRepository.findById(mno);
//100번이 존재하지 않더라도 오류를 반환하지 않음. 물론 객체도 반환되지 않음.
System.out.println("==============================");
if(result.isPresent()) {
Memo memo = result.get();
System.out.println(memo);
}
/*
* 조회 작업의 테스트는 findById()나 getOne()을 이용해서 엔티티 객체를 조회할 수 있다.
* findById()와 getOne()은 동작하는 방식이 조금 다르다.
* DB를 먼저 이용하는지, 필요한 순간까지 미루는지에 대한 차이이다.
*
* findById()는 DB를 먼저 이용해서 값을 가져온다.
* findById()를 실행한 순간에 이미 sql은 처리되었고
*
* findById()의 경우 java.util 패키지의 Optional 타입으로 반환되기 때문에
* 한 번 더 결과가 존재하는지 체크하는 형태로 작성하게 된다.
* "==============================" 부분은 SQL 처리 이후에 실행된다.
* */
}
@Transactional //트랜잭션 처리를 위해 사용하는 어노테이션. 없으면 오류 반환: no session
@Test //조회작업 테스트: getOne()사용
public void testSelect2(){
Long mno = 101L;
Memo memo = memoRepository.getOne(mno);
//리턴 값은 해당 객체이지만 필요한 순간까지 sql을 실행하지 않는다.
//해당 값이 테이블에 존재하지 않으면 오류 반환: Unable to find org.zerok.ex2.entity.Memo with id 100
//getOne()은 depricated됨. getReferenceById()로 대체. testSelect3()에서 사용
System.out.println("==============================");
System.out.println(memo);//실제 객체를 사용하는 순간에 SQL이 동작한다.
}
@Transactional //트랜잭션 처리를 위해 사용하는 어노테이션. 없으면 오류 반환: no session
@Test //조회작업 테스트: getOne()사용
public void testSelect3(){
Long mno = 101L;
Memo memo = memoRepository.getReferenceById(mno); //getOne() 대신에 사용
//리턴 값은 해당 객체이지만 필요한 순간까지 sql을 실행하지 않는다.
//해당 값이 테이블에 존재하지 않으면 오류 반환 : Unable to find org.zerok.ex2.entity.Memo with id 100
//getOne()은 depricated됨. getReferenceById()로 대체. testSelect3()에서 사용
System.out.println("==============================");
System.out.println(memo);//실제 객체를 사용하는 순간에 SQL이 동작한다.
}
@Test
public void testUpdate(){ //수정작업
Memo memo = Memo.builder().mno(100L).memoText("Update Text").build();
System.out.println(memoRepository.save(memo));
/*
* 수정작업은 등록작업과 동일하게 save()를 이용해서 처리한다.
* 내부적으로 해당 엔티티의 @Id 값이 일치하는지 확인해서 insert 혹은 update 작업을 처리한다.
*
* 여기서는 100번의 Memo객체를 만들고, save()를 호출한다.
* 호출결과를 보면 내부적으로 select 쿼리로 해당 번호의 Memo 객체를 확인하고
* 이를 update하는 것을 볼 수 있다.
*
* JPA는 엔티티 객체들을 메모리 상에 보관하려고 하기 때문에 특정한 엔티티 객체가 존재하는지
* 확인하는 select가 먼저 실행되고 해당 @Id를 가진 엔티티 객체가 있다면 update를,
* 그렇지 않다면 insert를 실행한다.
* */
}
@Test
public void testDelete(){
Long mno = 100L;
memoRepository.deleteById(mno);
/*
* 삭제 작업도 위와 동일한 개념이 적용된다. 삭제하려는 번호(mno)의 엔티티 객체가 있는지
* 먼저 확인(select)하고 이를 삭제 시도한다.
* deleteById()의 리턴 타입은 void이고 만일 해당 데이터가 존재하지 않으면
* org.springframework.dao.EmptyResultAccessException 예외를 발생시킴.
* */
}
@Test
public void testPageDefault(){
Pageable pageable = PageRequest.of(0, 10);
Page<Memo> result = memoRepository.findAll(pageable);
System.out.println(result);
System.out.println("--------------------------------------");
System.out.println("Total pages: " + result.getTotalPages()); // 총 몇 페이지
System.out.println("Total Count: " + result.getTotalElements()); // 총 개수
System.out.println("Total Number: " + result.getNumber()); // 현재 페이지 번호 0부터 시작
System.out.println("Page Size: " + result.getSize()); // 페이지당 데이터 개수
System.out.println("has next page?: " + result.hasNext()); // 다음 페이지 존재 여부
System.out.println("first page? : " + result.isFirst()); // 시작페이지(0) 여부
System.out.println("--------------------------------------");
for(Memo memo : result.getContent()) {
System.out.println(memo);
}
}
@Test
public void testSort(){
Sort sort1 = Sort.by("mno").descending();
Sort sort2 = Sort.by("memoText").ascending();
Sort sortAll = sort1.and(sort2); //and를 이용한 연결. memo는 desc로, memoText는 asc로 정렬
Pageable pageable = PageRequest.of(0, 10, sortAll);
Page<Memo> result = memoRepository.findAll(pageable);
result.get().forEach(memo -> {
System.out.println(memo);
});
}
@Test
public void testQueryMethod(){
List<Memo> list = memoRepository.findByMnoBetweenOrderByMnoDesc(70L, 80L);
for (Memo memo : list){
System.out.println(memo);
}
}
}
@Test
public void testPageDefault()
@Test
public void testSort()
@Test
public void testQueryMethod()
package org.zerok.ex2.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
import org.zerok.ex2.entity.Memo;
import java.util.List;
public interface MemoRepository extends JpaRepository<Memo, Long> {
//JpaRepository를 사용할 때는 엔티티 타입 정보(여기서는 Memo클래스)와 @Id 타입을 지정한다.
//SpringDataJpa는 인터페이스 선언만으로도 자동으로 bean으로 등록한다.
//(내부적으로는 인터페이스 타입에 맞는 객체를 생성해서 빈으로 등록한다.)
//선언이 끝났으면 test폴더-repository패키지생성-MemoRepositoryTests클래스를 작성해서 진행
List<Memo> findByMnoBetweenOrderByMnoDesc(Long from, Long to);
//쿼리메소드와 @Query를 사용하기 위해 선언. 이 메소드의 이름 자체가 질의문이 된다.
}
@Commit
@Transactional
@Test
public void testDeleteQueryMethod(){
memoRepository.deleteMemoByMnoLessThan(10L); //10번 전까지의 데이터를 삭제
package org.zerok.ex2.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
import org.zerok.ex2.entity.Memo;
import java.util.List;
public interface MemoRepository extends JpaRepository<Memo, Long> {
//JpaRepository를 사용할 때는 엔티티 타입 정보(여기서는 Memo클래스)와 @Id 타입을 지정한다.
//SpringDataJpa는 인터페이스 선언만으로도 자동으로 bean으로 등록한다.
//(내부적으로는 인터페이스 타입에 맞는 객체를 생성해서 빈으로 등록한다.)
//선언이 끝났으면 test폴더-repository패키지생성-MemoRepositoryTests클래스를 작성해서 진행
void deleteMemoByMnoLessThan(Long num);
//쿼리메소드와 @Query를 사용하기 위해 선언. 이 메소드의 이름 자체가 질의문이 된다.
}
'Framework > Spring' 카테고리의 다른 글
Thymeleaf 타임리프 기본 + Simple Sidebar (0) | 2022.06.28 |
---|---|
JpaRepository + @Query, nativeQuery = true (0) | 2022.06.23 |
JPA 인터페이스 생성 + CRUD 테스트 (insert, findById, getOne, getReferenceById save, deleteById) (0) | 2022.06.12 |
JPA 활용 + 클래스 생성 및 테이블 생성 (0) | 2022.06.09 |
리스트 또는 배열을 파라미터로 전달할 때의 처리 (0) | 2022.04.07 |
Comments