JPA와 Repository(간단히 CRUD)
JPA : JAVA Persistence API. ORM(Object Relational Mapping)으로 RDB의 정보를 객체지향으로 활용할 수 있도록 도와주는 도구. JSP의 DAO(Data Access Object)와 같다.
JPA는 Object와 RDB를 매핑시켜 데이터를 쉽게 다루는 기술을 제공한다. 쿼리보다 객체를 더 다루기 때문에 프로그래밍에 더 집중할 수 있게 해주는 라이브러리다.
JPA는 JpaRepository 인터페이스를 제공한다. Entity에 대해서 기본적인 CRUD를 사용할 수 있게 해준다.
간단히 만들 수 있다. repository 인터페이스를 만들고 JpaRepository<T,U> 인터페이스를 상속받는다. T는 저장할 객체의 타입이고, U는 PK의 타입이다. 따로 구현해야 하는 코드도 없다.
public interface UserRepository extends JpaRepository<User, Integer>
만약 JpaRepository를 상속받지 않으면 @Repository를 붙여 스프링이 관리할 수 있도록 해야 하지만, JpaRepository를 상속받기 때문에 자동으로 Bean으로 등록된다.(그래서 @Repository는 안붙여 된다.)
작성한 repository를 사용할 때는 의존성 주입을 통해 사용할 수 있다. @Autowired를 붙이면 의존성 주입을 받는다.
@Autowired가 붙으면 스프링은 해당 타입의 객체를 컨테이너에서 찾아 주입한다.(스프링이 싱글톤으로 객체를 관리)
JpaRepository 같은 경우 Bean으로 등록돼있기 때문에 주일될 수 있다.
@Autowired // 의존성 주입
private UserRepository userRepository;
JpaRepository의 CRUD 사용하기.
먼저 알 것 : save() 메소드는 전달받은 객체가 새로운 것인지 확인하고, 새로운 데이터라고 확인하면 insert 문을 날리고, 있는 데이터라면 select 쿼리와 update 쿼리를 날린다.(필드값이 같다고 해서 새로운 데이터가 아닌 것은 아니다.)
Create
repository.save(test) - DB에 test객체를 저장한다. 그리고 DB에 저장된 객체를 다시 리턴한다.
User user = new User();
... //user 필드 설정
User newUser = userRepository.save(user);
System.out.println(newUser);
Read
repository.findAll() 또는 findById() - findAll()은 리스트 형태로 테이블에 저장된 모든 레코드를 가져오고, findById()는 Id 값을 전달받아 객체를 가져온다.
Optional 형태로 가져온다. 그래서 ifPresent 문을 같이 사용한다.
Optional<User> user = userRepository.findById(1L);
user.ifPresent(selectUser -> {
System.out.println(selectUser);
});
Update
Read와 마찬가지로 먼저 객체를 가져온다. 만약 존재하면 객체의 값을 수정하고 save(test); 메소드로 값을 저장한다.
이 때 저장되는 객체는 Id값은 수정이 없어야 가져온 객체를 update(덮어쓰기)한다. 만약 여기서 id 값까지 바꿨다면 다른 걸 덮어쓰거나, 새롭게 생성된다.
Optional<User> user = userRepository.findById(1L);
user.ifPresent(seletUser -> {
seletUser.setAge(100);
userRepository.save(seletUser);
});
Delete
Read와 마찬가지로 먼저 객체를 가져온다. 만약 존재하면 delete(test); 메소드로 데이터를 삭제한다.
Junit의 Assertions의 assertTrue, assertFalse를 사용해서 값의 존재에 따라 에러를 발생시킬 수 있다.
Optional<User> user = userRepository.findById(1L);
Assertions.assertTrue(user.isPresent()); // true
user.ifPresent(seletUser -> {
userRepository.delete(seletUser);
});
Optional<User> deleteUser = userRepository.findById(1L);
Assertions.assertFalse(deleteUser.isPresent()); //true
보통 데이터를 검색할 때는 테이블의 Id값으로 검색하지 않고 이름이나 나이 같은 속성 같으로 검색한다. 이와 관련해 JPA는 Query Method를 제공한다.
Entity를 관리하는 Repository 인터페이스에서 쿼리 메소드를 선언할 수 있다.
예를 들어 이름으로 검색하는 메소드는 다음과 같이 선언할 수 있다.
Optional<Writer> findByName(String name);
이렇게 선언하면 JPA는 메소드 이름을 분석한다. findBy를 보고 select 쿼리란 것을 알 수 있고, 뒤에 대문자로 시작하는 문자를 속성값으로 찾는다. 이때 매개변수로 오는 name은 속성 이름과 일치하지 않아도 된다.
여러 속성으로 검색할 수 있다. 만약 나이와 이메일로 검색한다면 And를 붙여 선언한다.
Optional<Writer> findByNameAndEmail(String name, String email);
JpaRepository의 CRUD 기능을 컨트롤러의 메소드와 같이 사용하면 클라이언트로부터 받는 데이터를 DB에 저장하는 등의 처리를 할 수 있다.
@PostMapping("/join")
public User join(User user) {
userRepository.save(user);
}