JPA를 사용하기 위해서는 build.gradle에 의존성이 추가되어있어야 한다.
만약, 의존성이 추가되어있지 않다면, 추가해주도록 하자.
ORM
- db에서의 table과 Java 객체 간의 연결을 만들어주는 것
- 여기서 말하는 Java 객체는 Entity이다.
- 객체를 Entity로 선언하기 위해서는 @Entity를 추가하면 된다.
User class에 @Entity 선언하기
- @Entity만 선언하게 되면 User에 빨간 밑줄이 그어진다.
- 이는 Entity에는 PK가 반드시 필요하기 때문이다.
- id 값을 추가
- @GeneratedValue를 추가하여 순차적으로 증가하게 함
- 따라서, private Long id 는 자동으로 증가하는 숫자 값이고 User Table 객체의 PK 값인 ID가 된다.
Q. 그렇다면 해당 객체는 어떻게 저장하고 조회할 수 있을까?
A. Repository를 생성하면 된다.
- 패키지 안에 repository 폴더 생성
- JpaRepository를 상속 받음으로써 많은 JPA 관련 메서드들을 지원받는다.
- UserTest 코드 안에 AllArgsConstructor 에서 Error가 발생했다.
- id 값을 추가해주지 않아서 발생
- id 값을 추가해주면 해결된다.
JpaRepository를 상속받는 것 만으로도 JpaRepository의 많은 것을 활용할 수 있다.
Test Code 만들기
- @SpringBootTest로 Spring Context를 로딩해서 Test에 활용
- @Autowired를 통해 UserRepository 가져오기 (의존성 추가)
- crud() 메서드 test 코드 작성
- save()로 User를 저장
- findAll()로 전체를 조회
오류 발생
❗ Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "insert into [*]user (created_at, email, name, updated_at, id) values (?, ?, ?, ?, ?)"; expected "identifier"; SQL statement: ...
원인
user 가 예약어라서 사용할 수 없음
해결 방법
class 명 변경 User → Users
해결
- id는 1이 부여되었고, 위에는 NoArgsConstructor로 만들었기 때문에 Null 값이 들어갔다.
Q. 이런 메서드들은 어디에 있는 것일까?
ctrl을 누른 상태로 JpaRepository를 클릭하면 JpaRepository를 살펴볼 수 있다.
JPARepository 메서드 뜯어보기
List<T> findAll(); // table의 모든 data를 가져온다.
//test에서는 사용할지라도 실제 서비스에서는 성능적인 이슈로 잘 사용하지 않는다.
List<T> findAll(Sort sort); // 정렬 값이 추가된 메서드
List<T> findAllById(Iterable<ID> ids);
// id 값이 iterable(list)로 받아서 in 구문으로 조회해서 여러가지 Entity들을 조회
<S extends T> List<S> saveAll(Iterable<S> entities);
// Entity를 list 형식으로 받아서 한번에 db에 반영하도록 한다.
void flush();
// 현재 jpa context에서 가지고 있는 db 값을 db에 반영하도록 한다.
<S extends T> S saveAndFlush(S entity); // 저장한 데이터를 바로 db에 반영
<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);
default void deleteInBatch(Iterable<T> entities) {
deleteAllInBatch(entities);
}
// Entity를 iterable(list의 상위 인터페이스) 형식으로 받아서 한꺼번에 지우기
void deleteAllInBatch(Iterable<T> entities);
// 조건 없이 해당 테이블 모두 지우기 (실제 로직에서는 잘 안 쓰인다.)
void deleteAllByIdInBatch(Iterable<ID> ids);
void deleteAllInBatch();
T getOne(ID id); // id값으로 해당 Entity 조회
T getById(ID id);
T getReferenceById(ID id);
<S extends T> List<S> findAll(Example<S> example); // example을 이용한 findAll
<S extends T> List<S> findAll(Example<S> example, Sort sort);
PagingAndSortingRepository 뜯어보기
- CrudRepository를 상속 받고 있다.
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
// pageable parameter를 받아서 한번에 페이징을 쉽게 처리
CrudRepository 뜯어보기
- Repository를 상속 받고 있다.
<S extends T> S save(S entity); // Entity에 대한 저장
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
// Entity의 묶음을 가지고 한번에 저장
Optional<T> findById(ID id);
// Optional 객체로 매핑해서 return 해준다.
// getOne()과는 동작이 조금 다르다.
boolean existsById(ID id);
// 해당 객체의 존재 여부 확인
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> ids);
long count(); // 전체 Entity의 개수 가져오기
void deleteById(ID id);
void delete(T entity);
void deleteAllById(Iterable<? extends ID> ids);
void deleteAll(Iterable<? extends T> entities);
void deleteAll();
- 많이 사용되는 메서드들은 CrudRepository에 정의되어있다.
Repository 뜯어보기
- 아무것도 존재하지 않는다.
- 최상위 interface에 있는 Repository는 JPA에서 사용하는 domain Repository 타입이라고 하는 것을 알려주기 위한 interface
- 실제로 메서드에 대한 정의는 존재하지 않는다.
QueryByExampleExecutor 뜯어보기
<S extends T> Optional<S> findOne(Example<S> example);
<S extends T> Iterable<S> findAll(Example<S> example);
<S extends T> Iterable<S> findAll(Example<S> example, Sort sort);
<S extends T> Page<S> findAll(Example<S> example, Pageable pageable);
<S extends T> long count(Example<S> example);
<S extends T> boolean exists(Example<S> example);
<S extends T, R> R findBy(Example<S> example, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);
- example을 활용한 메서드들이 있다.
2023 KAKAO Tech Campus_BackEnd 선택 과정
Spring JPA와 Security 강의 정리 내용입니다.
'💻 개발 > Spring' 카테고리의 다른 글
Framework와 Project (0) | 2023.11.29 |
---|---|
Repository Interface 메소드 실습 (1) (0) | 2023.07.20 |
H2 DB 및 로그 설정 (0) | 2023.07.18 |
Lombok 알아보기 (0) | 2023.07.17 |
스프링 부트 프로젝트 생성 (0) | 2023.07.17 |