1. JPA(Java Persistence API) : 자바 오브젝트로 영구히 기록할때 사용하는 것
- Java 언어를 사용하여 객체와 관계형 데이터베이스 간의 매핑을 처리하는 데 사용되는 API
- Java와 관계형 DB간의 상호 작용을 추상화, 간소화 → DB와의 상호 작용을 더 쉽게 할 수 있음
SQL 쿼리를 직접 작성하지 않고도 객체를 데이터베이스에 저장, 검색, 수정, 삭제할 수 있음
- ORM(객체 관계 매핑) : 객체와 DB 테이블 간의 매핑을 정의할 수 있음
객체 지향 코드를 작성하고 DB와의 상호 작용은 JPA가 처리
- 객체 지향적 쿼리 : JPQL(Java Persistence Query Language)를 제공 → 객체에 대한 쿼리를 작성SQL과 비슷하지만 테이블이 아닌 엔티티와 속성을 대상으로 함
- 성능 최적화 : 지연 로딩(Lazy Loading)과 캐시(Caching) 기능
성능을 최적화에 불필요한 쿼리를 보내지 않고도 객체를 효율적으로 로드할 수 있음
- 트랜잭션 관리 : 트랜잭션을 관리하여 DB 상태의 일관성을 보장
JPA의 트랜잭션 관리 기능을 사용하여 DB 트랜잭션을 시작, 커밋 또는 롤백할 수 있음
- 포괄적인 표준 : Java EE의 일부로서 표준 사양으로서 제공
여러 개발자 및 프레임워크가 DB와 상호 작용, 다양한 JPA 구현이 서로 호환되는 장점을 제공
2. JPA Repository
- Java Persistence API를 사용하여 데이터베이스와 상호작용하는데 사용되는 인터페이스
Spring Framework의 일부인 Spring Data JPA에서 주로 사용
- CRUD 작업 지원 : DB에서 엔티티를 만들고, 읽고, 업데이트하고, 삭제하는데 필요한 기본 CRUD(Create, Read, Update, Delete) 작업을 지원
Create
save(S entity) : 엔티티를 저장
이미 존재하는 경우에는 업데이트, 존재하지 않는 경우에는 추가
Read
findById(ID id) : 주어진 ID에 해당하는 엔티티를 조회
findAll() : 모든 엔티티를 조회
findAllById(Iterable<ID> ids ): 주어진 ID 목록에 해당하는 모든 엔티티를 조회
existsById(ID id ): 주어진 ID에 해당하는 엔티티의 존재 여부를 확인
count() : 엔티티의 총 수를 반환
Update
save(S entity) : 엔티티를 저장, 이미 존재하는 경우에는 업데이트
Delete
deleteById(ID id) : 주어진 ID에 해당하는 엔티티를 삭제
delete(T entity) : 주어진 엔티티를 삭제
deleteAll() : 모든 엔티티를 삭제
- 그외 @Query 어노테이션으로 직접 작성 → 복잡한 동적쿼리는 EntityManager로 직접 작성
- 쿼리 메서드 : 메서드 이름을 기반으로 쿼리를 자동으로 생성하는 기능을 제공
- @Query 어노테이션 : 직접 JPQL 또는 네이티브 SQL 쿼리를 작성하여 사용할 수 있
- 페이징과 정렬 : 페이징 및 정렬 기능을 지원하여 대용량 데이터셋에서 효율적으로 작업
3. Optional
- Java 8에서 도입된 클래스
- 값의 존재 여부를 나타내는 컨테이너
- 메서드가 값을 반환할 때 사용, 값이 없을 수도 있는 상황에서 명시적으로 처리하기 위해 사용
- 해당하는 객체를 찾았을 때 : Optional에 담아 반환 or 비어있는 Optional 반환
4. ANSI SQL(American National Standards Institute, ANSI)
- SQL(Structured Query Language)의 표준
- DBMS에서 데이터를 관리하고 검색하는 데 사용되는 표준화된 쿼리 언어
- SQL의 표준을 정의, 다양한 DBMS 벤더들이 이 표준에 따라 SQL을 구현하도록 지침을 제공
- SQL 코드가 다른 DBMS 간에 이식성 보장, 특정 벤더에 종속되지 않도록 도와줌
- 표준 기능 : 기본적인 데이터베이스 작업을 위한 다양한 쿼리와 명령을 정의
데이터베이스 생성, 테이블 생성, 데이터 삽입, 갱신, 삭제, 데이터 검색 등 다양한 작업 수행
- 데이터 정의 언어 (DDL) : 테이블, 뷰, 인덱스 등 데이터베이스 객체를 정의하기 위한 명령
- 데이터 조작 언어 (DML) : 데이터를 삽입, 갱신, 삭제, 조회하는 등 데이터 조작에 사용되는 명령
- 데이터 제어 언어 (DCL) : 데이터베이스의 보안과 권한 관리를 위한 명령
- 데이터 검색 언어 (DSL): 데이터베이스에서 정보를 조회하기 위한 SELECT 문
5. 간단한 것 : JPA Repository → 복잡한 것 : QueryRepository
- 인터페이스는 인터페이스를 상속(extends)할 수 있음
- 인터페이스는 new해서 메모리에 띄울 수 없음
class 만들어서 implements해서 내부를 구현
→ 어노테이션을 통해서 IoC에 띄울 수 있음 , DI 가능
추상적인 것(부모)에 의존해서 DI해서 사용할 수 있음
package shop.mtcoding.blog.user; import org.springframework.data.jpa.repository.JpaRepository; // 자동 컴포넌트 스캔이 됨 -> @Reposirotry를 하지 않아도 메모리에 뜸 public interface UserJPARepository extends JpaRepository<User, Integer> { // 인터페이스는 인터페이스를 상속(extends)할 수 있음 }
- 무엇에 의존하는지, PK의 타입
- JPA가 자동화시켜서 구현해서 만들어줌
- 자동 컴포넌트 스캔이 됨 → @Reposirotry를 하지 않아도 메모리에 뜸
6. 단위 테스트하기
- save_test 하기
package shop.mtcoding.blog.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import shop.mtcoding.blog._core.errors.exception.Exception404; import shop.mtcoding.blog.user.User; import shop.mtcoding.blog.user.UserJPARepository; import java.util.Optional; @DataJpaTest // import 안해도 IoC에 띄워줌 public class UserJPARepositoryTest { @Autowired private UserJPARepository userJPARepository; @Test public void save_test(){ // given User user = User.builder() .username("happy") .password("1234") .email("happy@nate.com") .build(); // when // then } }
- findById_test 하기
- Optional<> : Null처리 하기
package shop.mtcoding.blog.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import shop.mtcoding.blog._core.errors.exception.Exception404; import shop.mtcoding.blog.user.User; import shop.mtcoding.blog.user.UserJPARepository; import java.util.Optional; @DataJpaTest // import 안해도 IoC에 띄워줌 public class UserJPARepositoryTest { @Autowired private UserJPARepository userJPARepository; @Test public void save_test(){ // given User user = User.builder() .username("happy") .password("1234") .email("happy@nate.com") .build(); // when // then } @Test public void findById_test(){ // given int id = 5; // when Optional<User> userOP = userJPARepository.findById(id); if(userOP.isPresent()) {// 존재하면 User user = userOP.get(); // 꺼내기 System.out.println("findById_test : " + user.getUsername()); } // 없으면 throw하기 // then } }
- findAll_test 하기
package shop.mtcoding.blog.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import shop.mtcoding.blog._core.errors.exception.Exception404; import shop.mtcoding.blog.user.User; import shop.mtcoding.blog.user.UserJPARepository; import java.util.Optional; @DataJpaTest // import 안해도 IoC에 띄워줌 public class UserJPARepositoryTest { @Autowired private UserJPARepository userJPARepository; @Test public void findAll_test() { // given // when userJPARepository.findAll(); // then } }
- order by로 정렬을 해야 함
- oerder by 추가하기
- JPA Repository에서 findAll()보고 order by하는 방법 찾아보기
package shop.mtcoding.blog.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.data.domain.Sort; import shop.mtcoding.blog._core.errors.exception.Exception404; import shop.mtcoding.blog.user.User; import shop.mtcoding.blog.user.UserJPARepository; import java.util.Optional; @DataJpaTest // import 안해도 IoC에 띄워줌 public class UserJPARepositoryTest { @Autowired private UserJPARepository userJPARepository; @Test public void findAll_test() { // given // when userJPARepository.findAll(Sort.by(Sort.Direction.DESC,"id")); // then } }
7. UserJPARepository 에 findByUsernameAndPassword() 만들기
package shop.mtcoding.blog.user; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; // 자동 컴포넌트 스캔이 됨 -> @Reposirotry를 하지 않아도 메모리에 뜸 public interface UserJPARepository extends JpaRepository<User, Integer> { // 인터페이스는 인터페이스를 상속(extends)할 수 있음 // 간단한 쿼리 작성하기(join 가능) // @Query("select u from User u where u.username = :username and u.password = :password") // 쿼리 메서드 -> 복잡도만 올라감, 그냥 쿼리 작성하기 User findByUsernameAndPassword(@Param("username")String username, @Param("password") String password); }
Share article