스프링 데이터 - 값이 null인 경우 매개 변수 무시
2개의 파라미터를 갖는 스프링 데이터 저장소 인터페이스를 원합니다.다음과 같은 동작을 할 수 있는 방법이 있습니까?
MyObject findByParameterOneAndParameterTwo( String parameterOne, String parameterTwo);
두 파라미터 모두 값이 있으면 정상적으로 동작하고 두 값에 대해 "AND"를 수행했으면 합니다.
예를 들어 두 번째 파라미터가 null인 경우 ParameterOne에서만 검색합니다.
좋은 의견이라도 있나?
저장소 메서드의 이름을 붙이는 것이 가능한지는 잘 모르겠지만 다음을 사용할 수 있습니다.@Query
맘에 들다
(:parameterOne is null or parameter1 = :parameterOne) and (:parameterTwo is null or parameter2 = :parameterTwo)
이 솔루션에는 스프링 데이터 JPA의 Query By Example 기능이 없습니다.이를 활용하여 이 문제를 해결할 수 있습니다.사용자 지정 쿼리 및 쿼리 작성기는 필요하지 않습니다.
이 스프링 데이터 쿼리:
ExampleMatcher matcher = ExampleMatcher.matching().withIgnoreNullValues();
Example<MyObject> exampleQuery = Example.of(new MyObject("foo", null), matcher);
List<MyObject> results = repository.findAll(exampleQuery);
다음과 같은 쿼리를 생성합니다.
select *
from myObject
where parameter1 = "foo"
다음과 같은 경우:
ExampleMatcher matcher = ExampleMatcher.matching().withIgnoreNullValues();
Example<MyObject> exampleQuery = Example.of(new MyObject("foo", "bar"), matcher);
List<MyObject> results = repository.findAll(exampleQuery);
수율:
select *
from myObject
where parameter1 = "foo"
and parameter2 = "bar"
멋있다!
주의: 고객님이 해야 할 일은Repository
인터페이스 추가QueryByExample
인터페이스입니다.이 작업은 다음 중 하나를 확장하여 수행할 수 있습니다.QueryByExample
직접 인터페이스 또는 인터폴리티를 통해JpaRepository
:
public interface MyObjectRepository extends JpaRepository<MyObject, Long> {}
현시점에서는 이것은 불가능합니다.Spring-data-jpa
.
이 있습니다.JIRA
아직 조사 중인 이 건에 관한 티켓Spring
팀.
그러나 회피책이 필요한 경우 간단한 기준 쿼리 예를 확인할 수 있습니다.
업데이트:
상기 티켓은 종료되었으며 스프링 팀은 복잡성이 수반되고 Query by Example이 실현 가능한 옵션이기 때문에 이 기능의 실장에 관심이 없습니다.이 댓글 좀 보세요.
그 방법은 다음과 같습니다.
@Query("SELECT c FROM Customer c WHERE (:name is null or c.name = :name) and (:email is null"
+ " or c.email = :email)")
List<Customer> findCustomerByNameAndEmail(@Param("name") String name, @Param("email") String email);
이 Kolobok을 먹어봐
@FindWithOptionalParams
Iterable<MyObject> findByParameterOneAndParameterTwo( String parameterOne, String parameterTwo);
- JPA 쿼리
@Query("SELECT c FROM Customer c WHERE (:name is null or c.name = :name)")
- JPA 쿼리(nativeQuery = true)
@Query(nativeQuery = true, "SELECT id, name FROM Customer WHERE (false = :nameOn OR name = :name)")
List<Entity> findAll(@Param(value = "nameOn") Boolean nameOn, @Param(value = "name ") String name);
- nativeQuery에서 이름이 null인 경우 이름을 EMTEMY 문자열로 변경해야 합니다.
3개의 클래스를 사용하여 Criteria Builder를 사용했습니다.
JPA를 사용한 저장소 인터페이스
@Repository
public interface NotificationRepository extends JpaRepository<Notification,
Long>, NotificationRepositoryCustom {
}
커스텀 인터페이스
public interface NotificationRepositoryCustom {
List<Notification> findNotificationByCustomerIdAndRecipientAndNotificationAckStatusAndNotificationRequestChannel
(Long customerId, String userId, List<String> status, List<String> channels);
}
NotificationRepositoryCustom 구현
public class NotificationRepositoryCustomImpl implements NotificationRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<Notification> findNotificationByCustomerIdAndRecipientAndNotificationAckStatusAndNotificationRequestChannel(Long customerId, String userId, List<String> status, List<String> channels) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Notification> query = cb.createQuery(Notification.class);
Root<Notification> notification = query.from(Notification.class);
List<Predicate> predicates = new ArrayList<Predicate>();
if (userId != null)
predicates.add(cb.equal(notification.get("recipient"), userId));
if (customerId != null)
predicates.add(cb.equal(notification.get("customerId"), customerId));
if (CollectionUtils.isNotEmpty(status))
predicates.add(notification.get("notificationAckStatus").get("ackStatusCode").in(status));
if (CollectionUtils.isNotEmpty(channels))
predicates.add(notification.get("notificationRequestChannel").get("notificationChannel").get("channelCode").in(channels));
if (!predicates.isEmpty()) {
query
.select(notification)
.where(cb.and(
predicates.toArray(new Predicate[predicates.size()])));
}
return entityManager.createQuery(query).getResultList();
}
}
봄/J에 처음 왔어요.PA 공간,
'예제별 쿼리' 사용
( in seviceImp )를 사용하고 있습니다.아래의 인수는 모두 옵션입니다./사용자의 선택에 따라 다릅니다.
`
.
if (!firstName.isEmpty() ) {
staff.setFirstName(firstName);
}
if (!lastName.isEmpty() ) {
staff.setLastName(lastName);
}
if (!ptAadhar.isEmpty() ) {
patient.setPtAadhar(ptAadhar);
}
if (!Cell.isEmpty() ) {
staff.setCell(Cell);
}
Example<StaffEntity> example = Example.of(staff);
List<StaffEntity> staffList =staffRepository.findAll(example);
.
이거 드셔보세요.
@Query(value = "SELECT pr FROM ABCTable pr " +
"WHERE((pr.parameterOne = :parameterOne) or (pr.parameterOne = null and :parameterOne = null)) and
((pr.parameterTwo = :parameterTwo) or (pr.parameterTwo = null and :parameterTwo = null)) ")
List<PaymentRequest> getSomething (@Param("parameterOne") String parameterOne,
@Param("parameterTwo") String parameterTwo);
파라미터에 늘 또는 빈 값이 있는지 확인하려면 다음과 같이 해야 합니다.
@Query("SELECT t FROM Test t WHERE (:parameterOne IS NULL) OR (:parameterOne = '')");
이 문제를 해결하려면 Spring JPA Data Specification을 사용하는 것이 좋습니다.
이 솔루션은 모든 데이터 유형에 대해 작동하며 모든 DB 기능(더 큰 기능/작은 기능/좋음/같음/또는 없음/등)을 허용합니다.
저는 개인적으로 비즈니스 로직/기준 빌더를 여기에 캡슐화하면 서비스 코드를 훨씬 더 쉽게 읽을 수 있다는 것을 알게 됩니다. 특히 사양 방법에 좋은 이름을 붙이면 더욱 그렇습니다.또한 공개 메서드를 사용하여 사양 코드를 보다 쉽게 읽을 수 있도록 개인 메서드를 사용할 수도 있습니다.
OP의 예에서는 다음 메서드로 클래스를 만듭니다.
public static Specification<Entity> equalsParameterOne(String parameterOne){
//If the specification is null it will be excluded from the SQL and ignored
if(parameterOne == null || parameterOne.length = 0) return null;
return (root, query, cb) -> cb.equal(root.get("fieldOne"), parameterOne);
}
public static Specification<Entity> equalsParameterTwo(String parameterTwo){
//If the specification is null it will be excluded from the SQL and ignored
if(parameterTwo== null || parameterTwo.length = 0) return null;
return (root, query, cb) -> cb.equal(root.get("fieldTwo"), parameterTwo);
}
다음으로 jpaRepo를 사용하는 서비스 코드에서 다음과 같이 findAll()과 함께 사용할 수 있습니다.
//Be careful with your parenthesis
Specification<Entity> customDynamicSpecs =
Specification
.where(equalsParameterOne(criteria.getParamOne()))
.and(equalsParameterTwo(criteria.getParamTwo()));
//.or().not()
//... as many as you want.
//findAll() can take Pageable or Sort as 2nd argument for extra functionality.
repo.findAll(customDynamicSpecs);
이 작업을 수행하려면 repo extends JpaSpecification을 선언해야 합니다.이그제큐티브나 스태틱한 Import는, 어느 누구라도 만족할 수 있는 것보다 몇개인가 더 많이 실시합니다.하지만 다시 말씀드리지만, 제게는 판독 가능한 코드가 승리합니다.
너도 그럴 수 있어.
저장소:
`MyObject findByParameterOneAndParameterTwo( String parameterOne, String parameterTwo);`
null parameterTwo를 전달하면 생성된 JPQL에 IS NULL 조건이 포함됩니다.
`myobject0_.parameterTwo is null`
::repository.findByParameterOneAndParameterTwo("D", null);
참고 자료: https://www.baeldung.com/spring-data-jpa-null-parameters#query-methods
Repo를 별도의 클래스로 사용할 수 있을지 모르겠지만 String Builder append 쿼리를 옵션 파라미터와 함께 사용할 수 있습니다.이거면 될 거야
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.append("select p.name from personDemographic p ");
Boolean flag = true;
if(parameterOne != null){
if(flag){
queryBuilder.append("where condition...");
flag=false;
}
}
if(parameterOne != null){
if(flag){
queryBuilder.append("where condition...");
flag = false;
}else{
queryBuilder.append("and condition...");
}
Query query = entityManager.createQuery(queryBuilder.toString());
언급URL : https://stackoverflow.com/questions/43780226/spring-data-ignore-parameter-if-it-has-a-null-value
'programing' 카테고리의 다른 글
리액트 훅: 콜백 내에서 최신 상태로 접근 (0) | 2023.03.11 |
---|---|
jsonpath 식을 사용한 어레이 크기 - Stefan Goessner JsonPath (0) | 2023.03.06 |
사용자 지정 위젯이 Visual Composer에 표시되지 않음 (0) | 2023.03.06 |
노드에서 HTTP 요청을 통해 JSON 가져오기JS (0) | 2023.03.06 |
플레이 프레임워크 2.1 - 각도JS 라우팅 - 최적의 솔루션? (0) | 2023.03.06 |