com.flowlogix.api.dao.JPAFinder Maven / Gradle / Ivy
/*
* Copyright (C) 2011-2024 Flow Logix, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.flowlogix.api.dao;
import com.flowlogix.jeedao.InheritableDaoHelper;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
/**
* Easily add a composable query enhancement criteria to
* {@link #findAll()} and {@link #findRange(long, long)} methods,
* as well as {@link #count()} methods
*
* Another differentiator is that this class doesn't require inheritance,
* although some use cases could inherit from {@link InheritableDaoHelper} class.
*
* Simple Example:
* {@snippet class="com.flowlogix.demo.jeedao.ExampleDAO" region="simpleExampleDAO"}
*
* Injected Example:
* {@snippet class="com.flowlogix.demo.jeedao.InjectedDAO" region="injectedExampleDAO"}
*
* Injected Example with non-default EntityManager:
* {@snippet class="com.flowlogix.demo.jeedao.InjectedNonDefaultDAO" region="injectedNonDefaultExampleDAO"}
*
* @param Entity Type
*
* @author lprimak
*/
public interface JPAFinder {
/**
* finds all entities
*
* @return query
*/
TypedQuery findAll();
/**
* find all entities with enriched, composable criteria
*
* Example:
*
* {@code findAll(enhancement::accept)}
*
* {@snippet class = "com.flowlogix.demo.jeedao.UserDAO" region = "daoParameters"}
*
* @param queryCriteria
* @return query
*/
TypedQuery findAll(Consumer> queryCriteria);
/**
* find entities given a specified range
*
* @param min minimum index, starting with zero
* @param max maximum index
* @return query
*/
TypedQuery findRange(long min, long max);
/**
* find entities with enriched, composable criteria given a specified range
*
* @param min minimum index, starting with zero
* @param max maximum index
* @param queryCriteria
* @return query
*/
TypedQuery findRange(long min, long max, Consumer> queryCriteria);
/**
* count rows
* @return row count
*/
long count();
/**
* count with enriched, composable criteria
*
* @param countQueryCriteria
* @return row count
*/
long count(Consumer> countQueryCriteria);
/**
* QueryCriteria record contains {@link CriteriaBuilder}, {@link Root} and {@link CriteriaQuery}
* @param Entity Type of Criteria
* @param builder
* @param root
* @param query
*/
record QueryCriteria(CriteriaBuilder builder, Root root, CriteriaQuery query) {
/**
* @return query criteria builder and root, without the JPA {@link CriteriaQuery} object
*/
public CriteriaBuilderAndRoot partial() {
return new CriteriaBuilderAndRoot<>(builder, root);
}
}
/**
* Specialized CountQueryCriteria record contains
* {@link CriteriaBuilder}, {@link Root} and {@link CriteriaQuery}{@code }
* @param Entity Type of Criteria
* @param builder
* @param root
* @param query
*/
record CountQueryCriteria(CriteriaBuilder builder, Root root, CriteriaQuery query) {
/**
* @return query criteria builder and root, without the JPA {@link CriteriaQuery} object
*/
public CriteriaBuilderAndRoot partial() {
return new CriteriaBuilderAndRoot<>(builder, root);
}
}
/**
* Partial query criteria, only {@link CriteriaBuilder} and {@link Root}
* Used by enriched count and find query methods / lambdas
*
* {@snippet class = "com.flowlogix.demo.jeedao.UserDAO" region = "daoParameters"}
*
* @param builder
* @param root
* @param
*/
record CriteriaBuilderAndRoot(CriteriaBuilder builder, Root root) { }
/**
* Convenience interface for use with {@link CriteriaBuilderAndRoot} and {@link QueryCriteria}
* and is able to compose many enhanced query lambdas together
*
* {@snippet class = "com.flowlogix.demo.jeedao.UserDAO" region = "daoParameters"}
* @param Entity Type
*/
interface QueryEnhancement extends BiConsumer, CriteriaQuery>> {
/**
* Convenience method reference for use in {@link JPAFinder#findAll(Consumer)}
* and {@link JPAFinder#findRange(long, long, Consumer)} parameters
*
* @param criteria
*/
default void accept(QueryCriteria criteria) {
accept(criteria.partial(), criteria.query());
}
/**
* Convenience method reference for use in {@link JPAFinder#count(Consumer)} parameters
* @param criteria
*/
default void accept(CountQueryCriteria criteria) {
accept(criteria.partial(), criteria.query());
}
/**
* Allows for composition of enhancements via method references
* @see BiConsumer#andThen(BiConsumer)
*
* @param after
* @return combination lambda
*/
default QueryEnhancement andThen(QueryEnhancement after) {
return (l, r) -> BiConsumer.super.andThen(after).accept(l, r);
}
}
}