💡 ORM(Object-Relational Mapping) - 객체와 관계형 데이터 베이스의 데이터를 매핑하여 '객체 지향적인 코드'를 작성 가능하게 하는 기술을 의미합니다.
- ORM을 사용하면 개발자는 SQL 쿼리를 직접 작성하는 대신, 자바 객체를 사용하여 데이터베이스의 레코드를 쉽게 생성, 조회, 수정, 삭제할 수 있습니다. 이로 인해 개발 과정이 단순화되고, 코드의 가독성이 향상됩니다. - 또한, 데이터베이스와 애플리케이션 코드 간의 중간 계층 역할을 하여, 데이터베이스의 구조가 변경되더라도 애플리케이션 코드를 수정하지 않아도 됩니다. 이는 유지보수 과정을 간소화시키며, 개발 효율성을 높일 수 있습니다
💡 Spring Boot JPA(Java Persistence API) - 데이터베이스를 쉽게 다루기 위한 '데이터 액세스 기술'로 ORM(Object-Relational Mapping) 기법을 사용하여 자바 애플리케이션에서 사용하는 객체와 관계형 데이터베이스 사이의 매핑을 관리하는 ORM 기술에 대한 API 표준 명세서(인터페이스) 의미합니다. - 예를 들어, 데이터베이스의 테이블을 ORM내에서는 ‘엔티티 라는 하나의 객체’로 관리되며, 데이터베이스의 컬럼의 경우는 ORM내에서는 하나의 객체의 속성으로 사용이 됩니다.
- 이를 통해, 개발자가 직접적인 SQL을 작성하지 않고도 데이터베이스에서 데이터를 저장, 업데이트, 삭제, 조회하는 등의 작업을 수행할 수 있게 해 줍니다. - JPA는 표준화된 API를 제공함으로써, 다양한 ORM 프레임워크(예: Hibernate, EclipseLink, OpenJPA 등)와의 호환성을 보장합니다. 이로 인해 개발자는 특정 ORM 프레임워크에 종속되지 않고 필요에 따라 다른 프레임워크로 쉽게 전환할 수 있습니다.
https://djcho.github.io/jpa/jpa-chapter1-3/
[더 알아보기] 💡 퍼시스턴스 프레임워크(Persistence Framework)
- 데이터를 영구적으로 저장하고 관리하는 데 도움을 주는 소프트웨어 도구나 라이브러리입니다. 이를 통해 개발자는 데이터베이스에 대한 복잡한 코드를 작성하지 않아도 되며 이로 인해 개발시간을 단축하고 코드의 품질을 향상할 수 있습니다. - 대표적인 퍼시스턴스 프레임워크로는 Hibernate, MyBatis 등이 있습니다.
- JpaRepository를 사용하면 상속받고 있는 PagingAndSortingRepository, CRUDRepository, Repository 인터페이스를 사용할 수 있습니다. - PagingAndSortingRepository를 사용하면 상속받고 있는 CRUDRepository, Repository 인터페이스를 사용할 수 있습니다. - CRUDRepository를 사용하면 상속 받고 있는 Repository 인터페이스를 사용할 수 있습니다.
인터페이스
요소 설명
Repository
Spring Data JPA의 핵심 리포지토리 인터페이스로, 기본적으로 매핑된 객체에 대한 CRUD 연산을 처리합니다.
CRUDRepository
Repository 인터페이스를 상속하고 있으며, 기본적인 CRUD 연산 외에도 count, deleteAll 등의 기능을 제공합니다.
PagingAndSortingRepository
CRUDRepository를 상속하고 있으며, 페이징 및 정렬 기능을 제공하는 메소드들을 추가로 제공합니다.
JpaRepository
PagingAndSortingRepository를 상속하고 있으며, JPA에 특화된 기능을 추가로 제공합니다. 이를 통해 flush, deleteInBatch 등의 메소드를 사용할 수 있습니다.
- 데이터 접근 계층(DAO)을 쉽고 간결하게 구현할 수 있는 Spring Data JPA의 핵심 구성 요소입니다. 이 인터페이스를 이용하면 개발자는 CRUD(Create, Read, Update, Delete) 연산을 위한 기본적인 메서드를 직접 구현할 필요 없이 공통적으로 사용되는 데이터 접근 로직을 제공받을 수 있습니다.
- 예를 들어, UserRepository라는 인터페이스가 Repository를 상속하고, 이 인터페이스 안에 findByUsername(String username)이라는 메서드를 정의하면, Spring Data JPA는 "SELECT * FROM User WHERE username =?"라는 SQL 쿼리를 자동으로 생성하고 실행합니다.
- Spring Data JPA에서 제공하는 인터페이스로 기본적인 CRUD(Create, Read, Update, Delete) 작업에 필요한 많은 메서드를 미리 정의해 놓고 있습니다. - 이를 상속받아 사용하면 개발자는 별도의 기본적인 데이터 액세스 로직을 작성하지 않고도 데이터베이스에서 데이터를 읽고 쓰는 작업을 수행할 수 있습니다. - 주요 메서드는 save(), findOne(), findAll(), count(), delete() 등이 있습니다.
💡 JpaRepository - Spring Data JPA에서 제공하는 인터페이스로, 개발자가 JPA를 더 쉽게 사용할 수 있도록 도와줍니다.
- JpaRepository를 상속받은 인터페이스를 만들면, 개발자는 별도의 구현 없이도 기본적인 CRUD 작업을 수행할 수 있는 여러 메서드를 사용할 수 있습니다. - 이는 Spring Data JPA가 제공하는 프록시 기반의 기술을 활용하여 가능합니다. 이외에도, JpaRepository는 페이징과 정렬, 플러시 등의 JPA의 고급 기능을 쉽게 사용할 수 있도록 지원합니다.
💡 Hibernate - JPA(Java Persistence API)의 API 표준 명세서(인터페이스)를 구현한 구현체 중 하나로 JPA 표준을 따르면서 자체적인 기능을 제공하는 ORM 프레임워크입니다.
- 데이터베이스와 객체 지향 프로그래밍 사이의 호환성 문제를 해결하기 위해 설계되었습니다. 자바 객체를 데이터베이스 테이블에 매핑하기 위해 JDBC를 사용합니다. - 데이터베이스의 테이블을 Java 클래스로 매핑하고, 테이블의 레코드를 클래스의 인스턴스로 매핑함으로써 이를 가능하게 합니다. 이러한 매핑을 통해 개발자는 SQL 쿼리 없이도 데이터베이스에서 데이터를 읽고 쓸 수 있습니다. - Spring Boot JPA를 설치하면 Hiberante 라이브러리가 포함되어 있습니다. 또한 Hibernate를 사용하면 HQL, JPQL, Criteria API를 사용이 가능합니다.(HQL → JPQL → Criteria API 순으로 나왔습니다)
💡 HQL(Hibernate Query Language) - 데이터베이스 테이블을 객체 지향적으로 조작할 수 있게 해주는 하이버네이트의 쿼리 언어입니다.
- SQL과 유사한 문법을 가지고 있지만, SQL이 데이터베이스 테이블에 직접 작업하는 반면, HQL은 객체에 작업하여 데이터베이스 독립성을 제공합니다. - 전체 객체 그래프를 쿼리 할 수 있으므로, 조인, 집계 및 하위 선택 등 SQL의 많은 기능을 사용할 수 있습니다. 하지만 HQL이 SQL과 다른 점 중 하나는 HQL이 객체 모델에 기반을 두고 있으므로, 클래스 이름과 클래스의 속성 이름을 사용한다는 것입니다.
💡 JPQL(Java Persistence Query Language) - 자바의 JPA(Java Persistence API) 사양의 일부로서 SQL과 유사한 문법을 갖지만 SQL은 데이터베이스 테이블에 직접 작업을 하는 반면에 JPQL은 엔티티 객체 중심으로 데이터를 처리하는 기능을 제공합니다.
- 주요한 기능은 엔티티, 엔티티의 관계, 엔티티의 단일 값 속성을 검색, 필터링 및 조작하는 기능을 제공합니다. - SQL 처리방식과 다르게 객체 지향적인 방식으로 데이터를 처리하므로 개발자는 SQL에 익숙한 데이터베이스 구조보다는 객체 지향 모델에 집중할 수 있습니다. 이를 통해 데이터베이스와 애플리케이션 사이의 유연성을 향상하고 개발시간을 줄일 수 있습니다.
💡 [참고] 예시 - 해당 예시는 JPQL을 사용하여 데이터베이스에서 특정 조건을 만족하는 데이터를 가져오는 예시입니다.
1. @PersistenceContext - 이 어노테이션은 EntityManager를 주입하기 위한 것입니다. EntityManager는 JPA의 핵심 컴포넌트로, 엔티티의 생명주기를 관리하며, 데이터베이스와의 CRUD 연산을 담당합니다.
2. String jpql = "SELECT t1 FROM tb_user t1 WHERE t1.user_st ='A'"; - 이 JPQL 쿼리는 user_st가 'A'인 모든 사용자를 선택합니다. JPA는 SQL과 유사한 JPQL을 제공하며, 이를 통해 개발자는 객체 지향적인 방식으로 데이터를 처리할 수 있습니다.
3., List <UserEntity> userList = em.createQuery(jpql, UserEntity.class).getResultList();: - 이 코드는 JPQL 쿼리를 실행하고, 결과를 UserEntity 객체의 리스트로 변환합니다. 4. for (UserEntity user : userList) - 이 코드는 조회된 사용자 리스트를 반복하여 각 사용자의 정보를 출력합니다.
💡 Criteria API - 자바의 JPA (Java Persistence API) 사양의 일부로서 기존 텍스트로 구성된 JPQL을 빌더 클래스를 사용하여 타입-세이프한 쿼리를 생성하는 API입니다.
- 기존 JPQL의 방식은 텍스트로 SQL를 작성하는 방식이기에 컴파일 타임에 오류를 검출할 수 없었으나, Criteria API에서는 타입-세이프 방식을 통해 컴파일 안정성을 제공하면서 컴파일 타임에 오류를 검출할 수 있습니다. - 또한, 런타임 시 동적 쿼리를 생성하는 데 유용합니다. 또한 동적 쿼리와 같은 복잡한 쿼리를 프로그래밍 방식으로 구성하여 객체 지향적인 방식으로 데이터베이스 쿼리를 작성할 수 있게 해 줍니다. - 단 해당 API는 복잡하고 장황한 코드를 만들 수 있어서 이해하고 유지보수하는 데 더 어려울 수 있습니다.
- Java 언어를 기반으로 타입-세이프한 쿼리 빌더 프레임워크(Query Builder Framework)를 의미합니다.
- 다양한 데이터베이스 플랫폼(RDBMS, NoSQL 등)에 접근하여 SQL과 유사한 문법을 ‘자바 코드’를 통해서 작성하고 데이터 처리를 수행합니다. 또한, 쿼리를 작성 할 때, 컴파일 시점에 타입에 대한 오류를 검출하여 런타임 시점에서 발생할 오류를 사전에 방지합니다.
[ 더 알아보기 ] 💡 JDO(Java Data Objects)
- 자바 애플리케이션에서 데이터베이스에 저장된 데이터에 접근하고 조작하는 API입니다. JDO는 객체 지향적인 접근을 제공하므로, 개발자는 SQL 쿼리를 직접 작성하지 않고도 데이터베이스의 데이터에 접근할 수 있습니다.
💡 주요 특징 1. 타입 세이프한 쿼리 작성 - 컴파일 시점에 쿼리에 대한 검증을 수행하여 런타임 에러를 방지합니다. 2. 플랫폼 독립적 - JPA, SQL, JDO, MongoDB, Lucene, Hibernate Search 등 다양한 플랫폼에서 사용 가능합니다. - 어떤 데이터 접근 기술을 사용하더라도 QueryDSL을 이용하면 타입 세이프한 쿼리를 작성하는 것이 가능합니다.
3. 다양한 쿼리 형태 지원 SELECT, UPDATE, DELETE 등의 쿼리 형태를 지원합니다.
💡 사용예시 - 해당 예시는 QueryDSL을 이용하여 “john”이라는 이름을 가진 모든 직원을 데이터베이스에서 조회하는 방법입니다. 1. QEmployee employee = QEmployee.employee; - QEmployee는 자동 생성된 Querydsl의 쿼리 타입입니다. 이를 사용하여 쿼리를 작성합니다.
2. JPAQuery <?> query = new JPAQuery <Void>(entityManager); - JPAQuery 객체를 생성합니다. 이 객체를 사용하여 쿼리를 실행합니다.
3. query.select(employee): - 쿼리의 select 절을 정의합니다. 여기서는 employee (즉, Employee 테이블의 모든 엔티티)를 선택합니다.
4. .from(employee) - 쿼리의 from 절을 정의합니다. 여기서는 Employee 테이블에서 데이터를 조회합니다.
5. .where(employee.firstName.eq("John")) - where 절을 정의합니다. 여기서는 firstName이 "John"인 모든 Employee 엔티티를 찾습니다.
6. .fetch(); - 쿼리를 실행하고 결과를 반환합니다. 여기서는 쿼리를 실행하여 firstName이 "John"인 모든 Employee 엔티티의 리스트를 가져옵니다.
@RepositorypublicclassUserDaoImplimplementsUserDao {
privatefinal JPAQueryFactory queryFactory;
privatefinalQUserEntityqUser= QUserEntity.userEntity;
/**
* 사용자 상태가 활성화 된 리스트를 조회합니다.
* @param userEntity
* @return
*/@Transactional(readOnly = true)public List<UserEntity> selectUserList(UserEntity userEntity) {
return queryFactory
.select(qUser)
.from(qUser)
.where(qUser.userSt.eq("A"))
.fetch();
}
}