# 락파일이 고정한 좌표에서 클래스패스를 만든다. Gradle 실행 없이 재현된다.
spring-data-jpa 4.0.7 -> <cache>/org.springframework.data/spring-data-jpa/4.0.7/spring-data-jpa-4.0.7.jar
spring-data-commons 4.0.7 -> <cache>/org.springframework.data/spring-data-commons/4.0.7/spring-data-commons-4.0.7.jar
querydsl-core 5.1.0 -> <cache>/com.querydsl/querydsl-core/5.1.0/querydsl-core-5.1.0.jar
querydsl-jpa 5.1.0 -> <cache>/com.querydsl/querydsl-jpa/5.1.0/querydsl-jpa-5.1.0-jakarta.jar
spring-core 7.0.9 -> <cache>/org.springframework/spring-core/7.0.9/spring-core-7.0.9.jar
spring-tx 7.0.9 -> <cache>/org.springframework/spring-tx/7.0.9/spring-tx-7.0.9.jar
jakarta.persistence-api 3.2.0 -> <cache>/jakarta.persistence/jakarta.persistence-api/3.2.0/jakarta.persistence-api-3.2.0.jar
slf4j-api 2.0.18 -> <cache>/org.slf4j/slf4j-api/2.0.18/slf4j-api-2.0.18.jar
#   app-bootstrap 의 락파일에 querydsl 이 있는가: 0

# 제한 없음 명세 팩토리가 어느 람다에 링크되는가
BootstrapMethods:
  0: #232 REF_invokeStatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$
    Method arguments:
      #233 (Ljakarta/persistence/criteria/Root;Ljakarta/persistence/criteria/CriteriaQuery;Ljakarta/persistenc
      #236 REF_invokeStatic org/springframework/data/jpa/domain/Specification.lambda$0:(Ljakarta/persistence/c
      #237 (Ljakarta/persistence/criteria/Root;Ljakarta/persistence/criteria/CriteriaQuery;Ljakarta/persistenc
#   그 람다의 본문
  private static jakarta.persistence.criteria.Predicate lambda$0(jakarta.persistence.criteria.Root, jakarta.persistence.criteria.CriteriaQuery, jakarta.persistence.criteria.CriteriaBuilder);
    Code:
       0: aconst_null
       1: areturn

# 그 명세와 자바 널을 두 검사에 각각 넣는다
Specification.unrestricted() 가 널인가 : false
그 명세의 toPredicate 가 돌려주는 값   : null
requireBounded(토큰 없이)  : 통과
requirePredicate           : 통과
requireBounded(널 명세)    : 거절 — a specification query requires a bounded predicate, or the explicit 'allow-unbounded-scan' token
requirePredicate(널 명세)  : 거절 — a specification query requires a bounded predicate

# 페이지 경계 검사는 그대로 남아 있다
34:    if (pageable.isUnpaged()) {
35-      throw new IllegalArgumentException(
36-          "a specification query requires a bounded page; unpaged reads whatever the table holds");
37-    }
#   반면 requirePredicate 는 Pageable 을 받지 않는다
47:  public static void requirePredicate(Specification<?> specification) {

# 형제 정책에 Querydsl 쪽 대응물을 넣는다
빈 BooleanBuilder 가 널인가 : false
hasValue                    : false
PredicatePolicy 판정        : 통과

# 형제 쪽 진입점은 항상 limit 을 붙이고, 그 리프에서 Querydsl 은 compileOnly 다
    JPAQuery<T> query = queryFactory.selectFrom(root);
    if (predicate != null) {
      query = query.where(predicate);
    }
    return query.offset(page.offset()).limit(page.size()).setHint(COMMENT_HINT, name.value());
  }
69:    compileOnly 'com.querydsl:querydsl-jpa:5.1.0:jakarta'
 * <p>Querydsl is an Advanced opt-in and is {@code compileOnly} for this leaf, so the Stable runtime
 * classpath never carries it. A deployment that wants it adds the artifact; one that does not is
 * unaffected by the existence of this class.
