Java 프로젝트에서 Criteria Builder 사용해 보기
자바, 스프링 부트
사이드 프로젝트나 직장에서 Java 및 SpringBoot로 REST API를 작성 중이라면 지금쯤 JPA를 사용했을 것입니다. CriteriaBuilder에 대해 들어본 적이 있을 것입니다. 그러나 그렇지 않은 경우 걱정하지 마십시오. 개인적으로 들어본 것은 불과 몇 년 전입니다. 이 타임라인에서 온라인으로 보면 Java Persistence 2.0( Source )부터 사용 가능한 것으로 보입니다.
이제 리팩토링 상황에서 쿼리의 문자열을 변경할 필요가 없는 방식으로 복잡한 쿼리를 작성하는 힘을 배울 때입니다. 이것은 Criteria Builder(패키지 javax.persistence
) 사용의 1부입니다.
쿼리를 작성하는 방법(오래 전). 지금 하지 마십시오. 2020년입니다:
String query = "Select usr.username from PlatformUser usr where usr.companyId = " + companyId;
쿼리에서 위치 매개변수를 사용하여 쿼리를 작성하는 방법:
@Repository
public interface PlatformUserRepository extends JpaRepository<PlatformUser, Long> {
@Query("SELECT item FROM PlatformUser usr where usr.companyId = ?1")
List<String> findAllCompanyUsernames (Long companyId);
}
Criteria Builder로 할 수 있는 작업:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<String> criteriaQuery = criteriaBuilder.createQuery(String.class);
Root<PlatformUser> root = criteriaQuery.from(PlatformUser.class);
criteriaQuery.select(root);
Query query = entityManager.createQuery(criteriaQuery);
List<String> results = query.getResultList();
엔티티 관리자에 액세스하려면 저장소 클래스에 이를 삽입해야 합니다.@PersistenceContext
private EntityManager entityManager;
Criteria Builder에 대한 문서가 내 관점에서 부족하므로 한 줄씩 설명하기 위해 최선을 다합니다.
데모 프로젝트의 예:
// Using Lombok plugin for getters and setters
@Getter
@Setter
public class CompanyHandyPersonDto {
private Long id;
private String fullName;
private Long companyId;
private Long tradeId;
private String comment;
}
테이블에서 간단한 선택:
@Repository
public class CompanyHandyPersonRepository implements CompanyHandyPersonRepositoryInterface {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<CompanyHandyPerson> findAllHandyPersons() {
// Get instance of criteria builder from an entity manager
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
// Create a query object
CriteriaQuery<CompanyHandyPerson> criteriaQuery = criteriaBuilder.createQuery(CompanyHandyPerson.class);
// Root of this query (I have no better idea of how to explain this)
Root<CompanyHandyPerson> root = criteriaQuery.from(CompanyHandyPerson.class);
// Choosing what data the query returns
criteriaQuery.select(root);
Query query = entityManager.createQuery(criteriaQuery);
// Run the query constructed above and extract the result
List<CompanyHandyPerson> results = query.getResultList();
return results;
}
}
조건을 만족하는 객체 목록 찾기:
@Override
public List<CompanyHandyPerson> findCompanyHandyPeopleThatAreSoftwareDevelopers() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<CompanyHandyPerson> criteriaQuery = criteriaBuilder.createQuery(CompanyHandyPerson.class);
Root<CompanyHandyPerson> root = criteriaQuery.from(CompanyHandyPerson.class);
// Check against the tradeId representing a specific one
criteriaQuery.select(root).where(criteriaBuilder.equal(root.get("tradeId"), 1L));
Query query = entityManager.createQuery(criteriaQuery);
List<CompanyHandyPerson> results = query.getResultList();
return results;
}
LIKE 조건이 있는 개체 목록을 찾습니다.
@Override
public List<Trade> findAllTradesWithNameSimilarTo(String tradeName) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Trade> criteriaQuery = criteriaBuilder.createQuery(Trade.class);
Root<Trade> root = criteriaQuery.from(Trade.class);
criteriaQuery.select(root).where(criteriaBuilder.like(root.get("name"), "%" + tradeName + "%"));
// Or without taking into consideration lower or upper cases
/**
* Predicate likePredicate = *criteriaBuilder.like(criteriaBuilder.lower(pantryItemRoot.get("name")), "%" + input.toLowerCase() + "%");
*pantryItemCriteriaQuery.select(pantryItemRoot).where(likePredicat*e);
*/
Query query = entityManager.createQuery(criteriaQuery);
List<Trade> results = query.getResultList();
return results;
}
주어진 Id 배열에서 Id가 있는 객체 목록을 찾습니다.
@Override
public List<CompanyHandyPerson> findCompanyHandyPeopleThatHaveOneOfTheGivenTradeId(Long[] tradeIds) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<CompanyHandyPerson> criteriaQuery = criteriaBuilder.createQuery(CompanyHandyPerson.class);
Root<CompanyHandyPerson> root = criteriaQuery.from(CompanyHandyPerson.class);
// Check tradeId is part of the given tradeIds
criteriaQuery.select(root)
.where(root.get("tradeId")
.in(tradeIds));
Query query = entityManager.createQuery(criteriaQuery);
List<CompanyHandyPerson> results = query.getResultList();
return results;
}
userFeedbackTitle 또는 userFeedbackDescription에 대해 비어 있지 않은 문자열 목록을 반환합니다(표현식 병합).
Note: a job has userFeedbackTitle
and userFeedbackDescription
. None of these are forced to have values. Both can be null, both or only one can have values.
@Override
public List<String> findAllFeedbackThatExists() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Job> criteriaQuery = criteriaBuilder.createQuery(Job.class);
Root<Job> root = criteriaQuery.from(Job.class);
// Check title and description and return when one of them is not null
CriteriaBuilder.Coalesce<Job> coalesceExpression = criteriaBuilder.coalesce();
coalesceExpression.value(root.get("userFeedbackTitle"));
coalesceExpression.value(root.get("userFeedbackDescription"));
criteriaQuery.select(coalesceExpression);
Query query = entityManager.createQuery(criteriaQuery);
List<String> results = query.getResultList();
return results;
}
위의 예에서 모든 null 값을 제거하려면 술어를 사용하여 제거할 수 있습니다.
Predicate<String> nullFilter = PojoPredicates.isValueNull();
results.removeIf(nullFilter);
작업 상태가 진행 중인 작업 요청이 있는 모든 사용자를 찾습니다.
@Override
public List<PlatformUser> findUsersThatHaveJobsInProgress() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<PlatformUser> userCriteriaQuery = criteriaBuilder.createQuery(PlatformUser.class);
Root<PlatformUser> userRoot = userCriteriaQuery.from(PlatformUser.class);
// Select user and job by user_id
Subquery<Job> jobSubQuery = userCriteriaQuery.subquery(Job.class);
Root<Job> jobRoot = jobSubQuery.from(Job.class);
jobSubQuery.select(jobRoot).where(criteriaBuilder.equal(jobRoot.get("userId"), userRoot.get("id")));
userCriteriaQuery.select(userRoot).where(criteriaBuilder.exists(jobSubQuery));
TypedQuery<PlatformUser> typedQuery = entityManager.createQuery(userCriteriaQuery);
List<PlatformUser> resultList = typedQuery.getResultList();
return resultList;
}
지금까지는 훌륭합니다. 다음으로 CriteriaBuilder가 더 나은 선택인 더 복잡한 상황에 대해 생각해 보겠습니다.
다음은 이에 대한 GitHub 프로젝트 데모입니다: Demo Project Source Code
Reference
이 문제에 관하여(Java 프로젝트에서 Criteria Builder 사용해 보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/gabriela/how-to-use-criteria-builder-in-your-java-project-4ag0
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
String query = "Select usr.username from PlatformUser usr where usr.companyId = " + companyId;
@Repository
public interface PlatformUserRepository extends JpaRepository<PlatformUser, Long> {
@Query("SELECT item FROM PlatformUser usr where usr.companyId = ?1")
List<String> findAllCompanyUsernames (Long companyId);
}
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<String> criteriaQuery = criteriaBuilder.createQuery(String.class);
Root<PlatformUser> root = criteriaQuery.from(PlatformUser.class);
criteriaQuery.select(root);
Query query = entityManager.createQuery(criteriaQuery);
List<String> results = query.getResultList();
private EntityManager entityManager;
// Using Lombok plugin for getters and setters
@Getter
@Setter
public class CompanyHandyPersonDto {
private Long id;
private String fullName;
private Long companyId;
private Long tradeId;
private String comment;
}
@Repository
public class CompanyHandyPersonRepository implements CompanyHandyPersonRepositoryInterface {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<CompanyHandyPerson> findAllHandyPersons() {
// Get instance of criteria builder from an entity manager
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
// Create a query object
CriteriaQuery<CompanyHandyPerson> criteriaQuery = criteriaBuilder.createQuery(CompanyHandyPerson.class);
// Root of this query (I have no better idea of how to explain this)
Root<CompanyHandyPerson> root = criteriaQuery.from(CompanyHandyPerson.class);
// Choosing what data the query returns
criteriaQuery.select(root);
Query query = entityManager.createQuery(criteriaQuery);
// Run the query constructed above and extract the result
List<CompanyHandyPerson> results = query.getResultList();
return results;
}
}
@Override
public List<CompanyHandyPerson> findCompanyHandyPeopleThatAreSoftwareDevelopers() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<CompanyHandyPerson> criteriaQuery = criteriaBuilder.createQuery(CompanyHandyPerson.class);
Root<CompanyHandyPerson> root = criteriaQuery.from(CompanyHandyPerson.class);
// Check against the tradeId representing a specific one
criteriaQuery.select(root).where(criteriaBuilder.equal(root.get("tradeId"), 1L));
Query query = entityManager.createQuery(criteriaQuery);
List<CompanyHandyPerson> results = query.getResultList();
return results;
}
@Override
public List<Trade> findAllTradesWithNameSimilarTo(String tradeName) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Trade> criteriaQuery = criteriaBuilder.createQuery(Trade.class);
Root<Trade> root = criteriaQuery.from(Trade.class);
criteriaQuery.select(root).where(criteriaBuilder.like(root.get("name"), "%" + tradeName + "%"));
// Or without taking into consideration lower or upper cases
/**
* Predicate likePredicate = *criteriaBuilder.like(criteriaBuilder.lower(pantryItemRoot.get("name")), "%" + input.toLowerCase() + "%");
*pantryItemCriteriaQuery.select(pantryItemRoot).where(likePredicat*e);
*/
Query query = entityManager.createQuery(criteriaQuery);
List<Trade> results = query.getResultList();
return results;
}
@Override
public List<CompanyHandyPerson> findCompanyHandyPeopleThatHaveOneOfTheGivenTradeId(Long[] tradeIds) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<CompanyHandyPerson> criteriaQuery = criteriaBuilder.createQuery(CompanyHandyPerson.class);
Root<CompanyHandyPerson> root = criteriaQuery.from(CompanyHandyPerson.class);
// Check tradeId is part of the given tradeIds
criteriaQuery.select(root)
.where(root.get("tradeId")
.in(tradeIds));
Query query = entityManager.createQuery(criteriaQuery);
List<CompanyHandyPerson> results = query.getResultList();
return results;
}
Note: a job has userFeedbackTitle
and userFeedbackDescription
. None of these are forced to have values. Both can be null, both or only one can have values.
@Override
public List<String> findAllFeedbackThatExists() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Job> criteriaQuery = criteriaBuilder.createQuery(Job.class);
Root<Job> root = criteriaQuery.from(Job.class);
// Check title and description and return when one of them is not null
CriteriaBuilder.Coalesce<Job> coalesceExpression = criteriaBuilder.coalesce();
coalesceExpression.value(root.get("userFeedbackTitle"));
coalesceExpression.value(root.get("userFeedbackDescription"));
criteriaQuery.select(coalesceExpression);
Query query = entityManager.createQuery(criteriaQuery);
List<String> results = query.getResultList();
return results;
}
Predicate<String> nullFilter = PojoPredicates.isValueNull();
results.removeIf(nullFilter);
@Override
public List<PlatformUser> findUsersThatHaveJobsInProgress() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<PlatformUser> userCriteriaQuery = criteriaBuilder.createQuery(PlatformUser.class);
Root<PlatformUser> userRoot = userCriteriaQuery.from(PlatformUser.class);
// Select user and job by user_id
Subquery<Job> jobSubQuery = userCriteriaQuery.subquery(Job.class);
Root<Job> jobRoot = jobSubQuery.from(Job.class);
jobSubQuery.select(jobRoot).where(criteriaBuilder.equal(jobRoot.get("userId"), userRoot.get("id")));
userCriteriaQuery.select(userRoot).where(criteriaBuilder.exists(jobSubQuery));
TypedQuery<PlatformUser> typedQuery = entityManager.createQuery(userCriteriaQuery);
List<PlatformUser> resultList = typedQuery.getResultList();
return resultList;
}
Reference
이 문제에 관하여(Java 프로젝트에서 Criteria Builder 사용해 보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/gabriela/how-to-use-criteria-builder-in-your-java-project-4ag0텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)