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
- 처음 만나는 AI 수학 with Python
- 구멍가게코딩단
- 목록처리
- baeldung
- 리눅스
- network configuration
- 데비안
- 페이징
- 스프링부트핵심가이드
- 코드로배우는스프링부트웹프로젝트
- 친절한SQL튜닝
- /etc/network/interfaces
- 선형대수
- 이터레이터
- 스프링 시큐리티
- 코드로배우는스프링웹프로젝트
- 네트워크 설정
- 알파회계
- 자료구조와 함께 배우는 알고리즘 입문
- 처음 만나는 AI수학 with Python
- resttemplate
- ㅒ
- d
- Kernighan의 C언어 프로그래밍
- 서버설정
- 자료구조와함께배우는알고리즘입문
- iterator
- GIT
- 티스토리 쿠키 삭제
- 자바편
Archives
- Today
- Total
bright jazz music
JPA 인터페이스 생성 + CRUD 테스트 (insert, findById, getOne, getReferenceById save, deleteById) 본문
Framework/Spring
JPA 인터페이스 생성 + CRUD 테스트 (insert, findById, getOne, getReferenceById save, deleteById)
bright jazz music 2022. 6. 12. 20:20jpa 인터페이스 생성
package org.zerok.ex2.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.zerok.ex2.entity.Memo;
public interface MemoRepository extends JpaRepository<Memo, Long> {
//JpaRepository를 사용할 때는 엔티티 타입 정보(여기서는 Memo클래스)와 @Id 타입을 지정한다.
//SpringDataJpa는 인터페이스 선언만으로도 자동으로 bean으로 등록한다.
//(내부적으로는 인터페이스 타입에 맞는 객체를 생성해서 빈으로 등록한다.)
//선언이 끝났으면 test폴더-repository패키지생성-MemoRepositoryTests클래스를 작성해서 진행
}
/*
*JpaRepository 인터페이스
* Spring Data Jpa는 Jp의 구현체인 Hibernate를 이용하기 위한 여러 API를 제공한다.
* 그 중 가장 많이 사용하는 것이 JpaRepository라는 인터페이스이다.
* 이러한 종류의 인터페이스의 기능을 통해서 JPA 관련 작업을 별도의 코드 없이 처리할 수 있도록 지원한다.
* CRUD, 페이징, 정렬 등의 처리도 인터페이스의 메서드를 호출하는 형태로 처리하는데,
* 기능에 따라서 상속구조로 추가적인 기능을 제공한다.
*
* 예) [JpaRepository -> PagingAndSortRepository]->[CrudRepository] -> [Repository]
*
* 일반적인 기능만을 사용할 때는 CrudRepository를 사용하는 것이 좋고, 모든 JPA관련 기능을
* 사용하고 싶을 때는 JpaRepository를 이용한다. 특별한 경우가 아니라면 JpaRepository를 이용하는 것이 무난하다.
*
*
* JpaRepository는 인터페이스이고, Spring Data Jpa는 이를 상속하는 인터페이스를
* 선언하는 것만으로도 모든 처리가 끝난다. 실제 동작 시에는 스프링이 내부적으로 해당 인터페이스에 맞는
* 코드를 생성하는 방식을 이용한다.
*
*
* */
인터페이스를 생성했다면 Test
test -> repository(패키지 생성) -> MemoRepositoryTests.java 생성
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.zerok.ex2.entity.Memo;
import javax.transaction.Transactional;
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 = 100L;
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 = 100L;
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 예외를 발생시킴.
* */
}
}
testInsertDummies()
findById()
getOne() : depricated됨. getReferenceById()를 사용할 것을 권장.
getReferenceById() : getOne()과 동일
=========먼저 실행됨. 그리고 나서 System.out.println(meno) 코드에서 객체가 실제 사용되어야 할 때 호출됨.
@Test
public void testUpdate()
Memo memo = Memo.builder().mno(100L).memoText("Update Text").build();
memoRepository.save(memo)
deleteById()
***
getOne()은 deprecated 처리 되었다.
이 메소드 대신에
getReferenceById() 를 사용할 것을 권장
'Framework > Spring' 카테고리의 다른 글
JpaRepository + @Query, nativeQuery = true (0) | 2022.06.23 |
---|---|
JpaRepository + 페이징, 쿼리메소드 (0) | 2022.06.23 |
JPA 활용 + 클래스 생성 및 테이블 생성 (0) | 2022.06.09 |
리스트 또는 배열을 파라미터로 전달할 때의 처리 (0) | 2022.04.07 |
추상클래는 왜 반드시 (0) | 2021.12.02 |
Comments