반응형
해당 글에서는 Spring Boot JPA에 대해 이해를 돕기 위해 작성한 글입니다.
💡 [참고] JPA 관련해서 구성 내용에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
분류 | 링크 |
Spring Boot Data JPA -1: ORM, JPA, Hibernate, QueryDSL 이론 | https://adjh54.tistory.com/421 |
Spring Boot Data JPA -2: 초기 환경 구성 + JpaRepository 활용 방법 | https://adjh54.tistory.com/422 |
Spring Boot Data JPA -3: 상세 JpaRepository 활용 방법 | https://adjh54.tistory.com/481 |
Spring Boot Data JPA 엔티티 어노테이션 -1 : 테이블 컬럼 단위 | https://adjh54.tistory.com/466 |
Spring Boot Data JPA 엔티티 어노테이션 -2 : 엔티티(테이블)간의 관계 | https://adjh54.tistory.com/477 |
Spring Boot Data JPA FetchType 이해하기 : 즉시/지연로딩 | https://adjh54.tistory.com/476 |
Spring Boot Data JPA : JPQL 활용 방법 | https://adjh54.tistory.com/479 |
Spring Boot Data JPA : Criteria API 활용 방법 | https://adjh54.tistory.com/483 |
Spring Boot Data JPA : QueryDSL 활용 방법-1 : 정의 및 구성요소 | https://adjh54.tistory.com/484 |
Spring Boot Data JPA : QueryDSL 활용 방법-2 : 초기 환경설정 및 활용예시 | https://adjh54.tistory.com/485 |
1) ORM(Object-Relational Mapping)과 JPA(Java Persistence API)
💡 ORM(Object-Relational Mapping)과 JPA(Java Persistence API)
- Spring Boot Starter JPA에서 제공하는 기능에 대해 이해하기 위해서는 ORM과 JPA 개념을 우선적으로 이해해야 합니다.
1. ORM(Object-Relational Mapping)
💡 ORM(Object-Relational Mapping)
- 객체와 관계형 데이터 베이스의 데이터를 매핑하여 '객체 지향적인 코드'를 작성 가능하게 하는 기술을 의미합니다.
- ORM을 사용하면 개발자는 SQL 쿼리를 직접 작성하는 대신, 자바 객체를 사용하여 데이터베이스의 레코드를 쉽게 생성, 조회, 수정, 삭제할 수 있습니다. 이로 인해 개발 과정이 단순화되고, 코드의 가독성이 향상됩니다.
- 또한, 데이터베이스와 애플리케이션 코드 간의 중간 계층 역할을 하여, 데이터베이스의 구조가 변경되더라도 애플리케이션 코드를 수정하지 않아도 됩니다. 이는 유지보수 과정을 간소화시키며, 개발 효율성을 높일 수 있습니다
💡 [참고] 실제 코드와 데이터베이스 테이블 간의 관계
💡 [참고] ORM 사용 예시
- 아래의 tb_user라는 관계형 데이터베이스의 테이블 및 컬럼이 존재합니다. 해당 컬럼과 아래의 Java 소스코드의 객체와 매핑이 됩니다.
- 해당 매핑을 통해 Java 객체를 하나의 테이블 컬럼으로 조회, 수정, 삭제할 수 있습니다.
💡 테이블 컬럼과 매핑된 객체를 아래와 같이 표현합니다.
package com.adjh.multiflexapi.jpa.entity;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.ToString;
import javax.persistence.*;
/**
* tb_user 테이블과 매핑 객체
*
* @author : jonghoon
* @fileName : UserEntity
* @since : 2/8/24
*/
@ToString
@Entity
@Table(name = "tb_user")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "user_sq")
private int userSq;
@Column(name = "user_id")
private String userId;
// 사용자 패스워드
@Column(name = "user_pw")
private String userPw;
// 사용자 이름
@Column(name = "user_nm")
private String userNm;
// 사용자 상태
@Column(name = "user_st")
private String userSt;
@Column(name = "user_email")
private String userEmail;
}
2. Spring Boot Data JPA(Java Persistence API)
💡 Spring Boot JPA(Java Persistence API)
- 데이터베이스를 쉽게 다루기 위한 '데이터 액세스 기술'로 ORM(Object-Relational Mapping) 기법을 사용하여 자바 애플리케이션에서 사용하는 객체와 관계형 데이터베이스 사이의 매핑을 관리하는 ORM 기술에 대한 API 표준 명세서(인터페이스) 의미합니다.
- 예를 들어, 데이터베이스의 테이블을 ORM내에서는 ‘엔티티 라는 하나의 객체’로 관리되며, 데이터베이스의 컬럼의 경우는 ORM내에서는 하나의 객체의 속성으로 사용이 됩니다.
- 이를 통해, 개발자가 직접적인 SQL을 작성하지 않고도 데이터베이스에서 데이터를 저장, 업데이트, 삭제, 조회하는 등의 작업을 수행할 수 있게 해 줍니다.
- JPA는 표준화된 API를 제공함으로써, 다양한 ORM 프레임워크(예: Hibernate, EclipseLink, OpenJPA 등)와의 호환성을 보장합니다. 이로 인해 개발자는 특정 ORM 프레임워크에 종속되지 않고 필요에 따라 다른 프레임워크로 쉽게 전환할 수 있습니다.
[더 알아보기]
💡 퍼시스턴스 프레임워크(Persistence Framework)
- 데이터를 영구적으로 저장하고 관리하는 데 도움을 주는 소프트웨어 도구나 라이브러리입니다. 이를 통해 개발자는 데이터베이스에 대한 복잡한 코드를 작성하지 않아도 되며 이로 인해 개발시간을 단축하고 코드의 품질을 향상할 수 있습니다.
- 대표적인 퍼시스턴스 프레임워크로는 Hibernate, MyBatis 등이 있습니다.
2) JPA 인터페이스
1. JPA 인터페이스 구조
💡 JPA 인터페이스 구조
- 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 등의 메소드를 사용할 수 있습니다. |
2. Repository <T, ID>
💡 Repository
- 데이터 접근 계층(DAO)을 쉽고 간결하게 구현할 수 있는 Spring Data JPA의 핵심 구성 요소입니다. 이 인터페이스를 이용하면 개발자는 CRUD(Create, Read, Update, Delete) 연산을 위한 기본적인 메서드를 직접 구현할 필요 없이 공통적으로 사용되는 데이터 접근 로직을 제공받을 수 있습니다.
- 예를 들어, UserRepository라는 인터페이스가 Repository를 상속하고, 이 인터페이스 안에 findByUsername(String username)이라는 메서드를 정의하면, Spring Data JPA는 "SELECT * FROM User WHERE username =?"라는 SQL 쿼리를 자동으로 생성하고 실행합니다.
리턴 타입 | 메서드 | 설명 |
void | deleteAllByIdInBatch(Iterable<ID> ids) | 주어진 id를 가진 엔티티를 단일 쿼리로 삭제합니다. |
void | deleteAllInBatch() | 모든 엔티티를 배치 호출에서 삭제합니다. |
void | deleteAllInBatch(Iterable<T> entities) | 주어진 엔티티를 배치로 삭제하며, 이는 단일 쿼리를 생성합니다. |
default void | deleteInBatch(Iterable<T> entities) | 사용 중단. 대신 deleteAllInBatch(Iterable)를 사용하세요. |
<S extends T>List<S> | findAll(Example<S> example) | 예제에 해당하는 모든 항목을 찾습니다. |
<S extends T>List<S> | findAll(Example<S> example, Sort sort) | 예제에 해당하는 모든 항목을 sort 순서로 찾습니다. |
void | flush() | 모든 보류 중인 변경 사항을 데이터베이스에 반영합니다. |
T | getById(ID id) | 사용 중단. 대신 getReferenceById(ID)를 사용하세요. |
T | getOne(ID id) | 사용 중단. 대신 getReferenceById(ID)를 사용하세요. |
T | getReferenceById(ID id) | 주어진 식별자를 가진 엔티티에 대한 참조를 반환합니다. |
<S extends T>List<S> | saveAllAndFlush(Iterable<S> entities) | 모든 엔티티를 저장하고 즉시 변경 사항을 반영합니다. |
<S extends T>S | saveAndFlush(S entity) | 엔티티를 저장하고 즉시 변경 사항을 반영합니다. |
3. CRUDRepository <T, ID>
💡 CRUDRepository
- Spring Data JPA에서 제공하는 인터페이스로 기본적인 CRUD(Create, Read, Update, Delete) 작업에 필요한 많은 메서드를 미리 정의해 놓고 있습니다.
- 이를 상속받아 사용하면 개발자는 별도의 기본적인 데이터 액세스 로직을 작성하지 않고도 데이터베이스에서 데이터를 읽고 쓰는 작업을 수행할 수 있습니다.
- 주요 메서드는 save(), findOne(), findAll(), count(), delete() 등이 있습니다.
리턴 타입 | 메서드 | 설명 |
long | count() | 엔티티의 총 개수를 반환합니다. |
void | delete(T entity) | 주어진 엔티티를 삭제합니다. |
void | deleteAll() | 레포지토리에서 관리하는 모든 엔티티를 삭제합니다. |
void | deleteAll(Iterable<? extends T> entities) | 주어진 엔티티를 모두 삭제합니다. |
void | deleteAllById(Iterable<? extends ID> ids) | 주어진 ID를 가진 모든 엔티티를 삭제합니다. |
void | deleteById(ID id) | 주어진 id의 엔티티를 삭제합니다. |
boolean | existsById(ID id) | 주어진 id를 가진 엔티티가 존재하는지 확인합니다. |
Iterable<T> | findAll() | 모든 엔티티를 반환합니다. |
Iterable<T> | findAllById(Iterable<ID> ids) | 주어진 ID를 가진 모든 엔티티를 반환합니다. |
Optional<T> | findById(ID id) | id로 엔티티를 검색합니다. |
<S extends T>S | save(S entity) | 주어진 엔티티를 저장합니다. |
<S extends T>Iterable<S> | saveAll(Iterable<S> entities) | 주어진 모든 엔티티를 저장합니다. |
4. PagingAndSortingRepository <T, ID>
💡 PagingAndSortingRepository
- Spring Data Repository의 하나로, 페이징 및 정렬 기능을 제공합니다. 이 인터페이스를 사용하면 개발자는 페이징 및 정렬 기능이 포함된 CRUD 작업을 수행할 수 있습니다.
- JpaRepository와 같은 다른 Spring Data Repository와 달리, 특정 도메인 클래스에 대한 추가 쿼리 메서드를 제공하지 않습니다.
리턴 타입 | 메서드 | 설명 |
Page<T> | findAll(Pageable pageable) | Pageable 객체에 제공된 페이징 제한을 충족하는 엔티티의 Page를 반환합니다. |
Iterable<T> | findAll(Sort sort) | 주어진 옵션에 의해 정렬된 모든 엔티티를 반환합니다. |
5. JpaRepository <T, ID>
💡 JpaRepository
- Spring Data JPA에서 제공하는 인터페이스로, 개발자가 JPA를 더 쉽게 사용할 수 있도록 도와줍니다.
- JpaRepository를 상속받은 인터페이스를 만들면, 개발자는 별도의 구현 없이도 기본적인 CRUD 작업을 수행할 수 있는 여러 메서드를 사용할 수 있습니다.
- 이는 Spring Data JPA가 제공하는 프록시 기반의 기술을 활용하여 가능합니다. 이외에도, JpaRepository는 페이징과 정렬, 플러시 등의 JPA의 고급 기능을 쉽게 사용할 수 있도록 지원합니다.
리턴 타입 | 메서드 | 설명 |
void | deleteAllByIdInBatch(Iterable<ID> ids) | 단일 쿼리를 사용하여 주어진 id로 식별된 엔티티를 삭제합니다. |
void | deleteAllInBatch() | 배치 호출에서 모든 엔티티를 삭제합니다. |
void | deleteAllInBatch(Iterable<T> entities) | 주어진 엔티티를 배치에서 삭제합니다. 이는 단일 쿼리를 생성합니다. |
default void | deleteInBatch(Iterable<T> entities) | 사용되지 않음. 대신 deleteAllInBatch(Iterable)를 사용하세요. |
<S extends T>List<S> | findAll(Example<S> example) | |
<S extends T>List<S> | findAll(Example<S> example, Sort sort) | |
void | flush() | 모든 보류 중인 변경 사항을 데이터베이스에 강제로 적용합니다. |
T | getById(ID id) | 사용되지 않음. 대신 getReferenceById(ID)를 사용하세요. |
T | getOne(ID id) | 사용되지 않음. 대신 getReferenceById(ID)를 사용하세요. |
T | getReferenceById(ID id) | 주어진 식별자를 가진 엔티티에 대한 참조를 반환합니다. |
<S extends T>List<S> | saveAllAndFlush(Iterable<S> entities) | 모든 엔티티를 저장하고 변경 사항을 즉시 강제로 적용합니다. |
<S extends T>S | saveAndFlush(S entity) | 엔티티를 저장하고 변경 사항을 즉시 강제로 적용합니다. |
3) JPA(Java Persistence API) 구현체 - Hibernate
💡 Hibernate
- JPA(Java Persistence API)의 API 표준 명세서(인터페이스)를 구현한 구현체 중 하나로 JPA 표준을 따르면서 자체적인 기능을 제공하는 ORM 프레임워크입니다.
- 데이터베이스와 객체 지향 프로그래밍 사이의 호환성 문제를 해결하기 위해 설계되었습니다. 자바 객체를 데이터베이스 테이블에 매핑하기 위해 JDBC를 사용합니다.
- 데이터베이스의 테이블을 Java 클래스로 매핑하고, 테이블의 레코드를 클래스의 인스턴스로 매핑함으로써 이를 가능하게 합니다. 이러한 매핑을 통해 개발자는 SQL 쿼리 없이도 데이터베이스에서 데이터를 읽고 쓸 수 있습니다.
- Spring Boot JPA를 설치하면 Hiberante 라이브러리가 포함되어 있습니다. 또한 Hibernate를 사용하면 HQL, JPQL, Criteria API를 사용이 가능합니다.(HQL → JPQL → Criteria API 순으로 나왔습니다)
1. HQL(Hibernate Query Language)
💡 HQL(Hibernate Query Language)
- 데이터베이스 테이블을 객체 지향적으로 조작할 수 있게 해주는 하이버네이트의 쿼리 언어입니다.
- SQL과 유사한 문법을 가지고 있지만, SQL이 데이터베이스 테이블에 직접 작업하는 반면, HQL은 객체에 작업하여 데이터베이스 독립성을 제공합니다.
- 전체 객체 그래프를 쿼리 할 수 있으므로, 조인, 집계 및 하위 선택 등 SQL의 많은 기능을 사용할 수 있습니다. 하지만 HQL이 SQL과 다른 점 중 하나는 HQL이 객체 모델에 기반을 두고 있으므로, 클래스 이름과 클래스의 속성 이름을 사용한다는 것입니다.
package com.adjh.multiflex.jpa.repository;
import com.adjh.multiflex.jpa.entity.UserEntity;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
/**
* HQL 사용예시
*
* @author : jonghoon
* @fileName : UserRepository
* @since : 2/9/24
*/
@Repository
public class UserRepository {
@PersistenceContext
private EntityManager em;
/**
* 사용자 리스트 조회
*
* @param userEntity
* @return
*/
public List<UserEntity> selectUserList(UserEntity userEntity) {
// Hibernate 설정 파일을 읽어들이는 Configuration 객체를 생성합니다.
Configuration configuration = new Configuration().configure();
// Configuration 객체에서 SessionFactory 객체를 가져옵니다.
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 세션 팩토리에서 세션을 가져옵니다.
Session session = sessionFactory.openSession();
// 트랜잭션을 시작합니다.
session.beginTransaction();
// UserEntity 클래스의 userSt 속성이 'A'인 객체를 쿼리합니다.
Query query = session.createQuery("FROM UserEntity WHERE userSt = A");
List<UserEntity> userList = query.list();
// 결과를 출력합니다.
for (UserEntity employee : userList) {
System.out.println(employee.getUserNm());
}
// 트랜잭션을 커밋합니다.
session.getTransaction().commit();
// 세션을 닫습니다.
session.close();
return userList;
}
}
2. JPQL(Java Persistence Query Language)
💡 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)
- 이 코드는 조회된 사용자 리스트를 반복하여 각 사용자의 정보를 출력합니다.
package com.adjh.multiflex.jpa.repository;
import com.adjh.multiflex.jpa.entity.UserEntity;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
/**
* JQPL 사용예시
*
* @author : jonghoon
* @fileName : UserRepository
* @since : 2/9/24
*/
@Repository
public class UserRepository {
@PersistenceContext
private EntityManager em;
/**
* 사용자 리스트 조회
*
* @param userEntity
* @return
*/
public List<UserEntity> selectUserList(UserEntity userEntity) {
// JPQL 쿼리를 작성합니다.
String jpql = "SELECT t1 FROM tb_user t1 WHERE t1.user_st ='A'";
// 쿼리를 생성하고 실행합니다.
List<UserEntity> userList = em.createQuery(jpql, UserEntity.class).getResultList();
// 조회된 Member 엔티티를 출력합니다.
for (UserEntity user : userList) {
System.out.println("userName = " + user.getUserNm());
}
}
}
3. Criteria API
💡 Criteria API
- 자바의 JPA (Java Persistence API) 사양의 일부로서 기존 텍스트로 구성된 JPQL을 빌더 클래스를 사용하여 타입-세이프한 쿼리를 생성하는 API입니다.
- 기존 JPQL의 방식은 텍스트로 SQL를 작성하는 방식이기에 컴파일 타임에 오류를 검출할 수 없었으나, Criteria API에서는 타입-세이프 방식을 통해 컴파일 안정성을 제공하면서 컴파일 타임에 오류를 검출할 수 있습니다.
- 또한, 런타임 시 동적 쿼리를 생성하는 데 유용합니다. 또한 동적 쿼리와 같은 복잡한 쿼리를 프로그래밍 방식으로 구성하여 객체 지향적인 방식으로 데이터베이스 쿼리를 작성할 수 있게 해 줍니다.
- 단 해당 API는 복잡하고 장황한 코드를 만들 수 있어서 이해하고 유지보수하는 데 더 어려울 수 있습니다.
Criteria 구성 요소 | 설명 |
CriteriaBuilder | Criteria 쿼리의 시작점을 의미하며 EntityManager에서 인스턴스를 얻을 수 있습니다 |
CriteriaQuery | 쿼리를 정의하는데 사용되며 CriteriaBuilder를 사용하여 인스턴스를 생성합니다 |
Root | From 절을 표현하는데 사용됩니다. |
💡 사용 예시
- 해당 예시에서는 Spring JPA의 Criteria API를 이용하여 사용자 리스트를 조회하는 예시입니다.
1. @PersistenceContext
- EntityManager를 주입하기 위해 사용됩니다. EntityManager는 JPA의 핵심 컴포넌트로, 엔티티의 생명주기를 관리하며, 데이터베이스와의 CRUD(Create, Read, Update, Delete) 연산을 담당합니다.
2. selectUserList()
- UserEntity를 입력받아 사용자 리스트를 반환합니다.
3. CriteriaBuilder builder = em.getCriteriaBuilder();
- CriteriaBuilder 인스턴스를 생성합니다.
4. CriteriaBuilder
- Criteria 쿼리의 생성을 돕습니다.
5. CriteriaQuery <UserEntity> query = builder.createQuery(UserEntity.class);
- CriteriaQuery 인스턴스를 생성합니다.
5. Root <UserEntity> root = query.from(UserEntity.class);
- Root 인스턴스를 생성합니다. Root는 쿼리의 루트 엔티티를 나타냅니다.
6. query = query.select(root).where(builder.equal(root.get("userSt"), "A"));
- 쿼리를 구성합니다. 이 쿼리는 userSt 필드가 'A'인 모든 사용자를 선택합니다.
7. return em.createQuery(query).getResultList();
- 쿼리를 실행하고 결과를 UserEntity 객체의 리스트로 반환합니다.
package com.adjh.multiflex.jpa.repository;
import com.adjh.multiflex.jpa.entity.UserEntity;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.List;
/**
* 사용자 리스트 조회
*
* @author : jonghoon
* @fileName : UserRepository
* @since : 2/9/24
*/
@Repository
public class UserRepository {
@PersistenceContext
private EntityManager em;
/**
* 사용자 리스트 조회
*
* @param userEntity
* @return
*/
public List<UserEntity> selectUserList(UserEntity userEntity) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<UserEntity> query = builder.createQuery(UserEntity.class);
Root<UserEntity> root = query.from(UserEntity.class);
query = query.select(root)
.where(
builder.equal(root.get("userSt"), "A")
);
return em.createQuery(query).getResultList();
}
}
4) QueryDSL
💡 QueryDSL
- Java 언어를 기반으로 타입-세이프한 쿼리 빌더 프레임워크(Query Builder Framework)를 의미합니다.
- 다양한 데이터베이스 플랫폼(RDBMS, NoSQL 등)에 접근하여 SQL과 유사한 문법을 ‘자바 코드’를 통해서 작성하고 데이터 처리를 수행합니다. 또한, 쿼리를 작성 할 때, 컴파일 시점에 타입에 대한 오류를 검출하여 런타임 시점에서 발생할 오류를 사전에 방지합니다.
[ 더 알아보기 ]
💡 JDO(Java Data Objects)
- 자바 애플리케이션에서 데이터베이스에 저장된 데이터에 접근하고 조작하는 API입니다. JDO는 객체 지향적인 접근을 제공하므로, 개발자는 SQL 쿼리를 직접 작성하지 않고도 데이터베이스의 데이터에 접근할 수 있습니다.
1. 주요 특징
💡 주요 특징
1. 타입 세이프한 쿼리 작성
- 컴파일 시점에 쿼리에 대한 검증을 수행하여 런타임 에러를 방지합니다.
2. 플랫폼 독립적
- JPA, SQL, JDO, MongoDB, Lucene, Hibernate Search 등 다양한 플랫폼에서 사용 가능합니다.
- 어떤 데이터 접근 기술을 사용하더라도 QueryDSL을 이용하면 타입 세이프한 쿼리를 작성하는 것이 가능합니다.
3. 다양한 쿼리 형태 지원
SELECT, UPDATE, DELETE 등의 쿼리 형태를 지원합니다.
2. 사용예시
💡 사용예시
- 해당 예시는 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 엔티티의 리스트를 가져옵니다.
@Repository
public class UserDaoImpl implements UserDao {
private final JPAQueryFactory queryFactory;
private final QUserEntity qUser = 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();
}
}
오늘도 감사합니다. 😀
반응형