Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.e6tech.elements.persist.criteria.Select Maven / Gradle / Ivy
/*
* Copyright 2015-2019 Futeh Kao
*
* 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 net.e6tech.elements.persist.criteria;
import net.e6tech.elements.common.interceptor.Interceptor;
import net.e6tech.elements.common.reflection.Primitives;
import net.e6tech.elements.common.reflection.Reflection;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.*;
import javax.persistence.metamodel.EntityType;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* Created by futeh.
*/
@SuppressWarnings("unchecked")
public class Select extends Statement {
private static final String GETTER_MSG = "Only accepts getter";
private Select parent;
private int maxResults = -1;
private int firstResult = -1;
private List> selections = new ArrayList<>();
private Map hints = new HashMap<>();
public Select(Where where, Root root) {
super(where, root);
}
protected Select(Select parent, Where where, From root) {
super(where, root);
this.parent = parent;
this.selections = parent.selections;
}
public static Select create(EntityManager entityManager, Class cls) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery query = builder.createQuery();
Root root = query.from(cls);
Where where = new Where(entityManager, builder, query, root);
return new Select<>(where, root);
}
public Select hint(String hint, Object value) {
hints.put(hint, value);
return this;
}
public Select removeHint(String hint) {
hints.remove(hint);
return this;
}
public void addConverter(Class from, Class to, Function function) {
where.addConverter(from, to, function);
}
public void removeConverter(Class from, Class to) {
where.removeConverter(from, to);
}
public T withConverter(Class from, Class to, Function function) {
addConverter(from, to, function);
return where.getTemplate();
}
public Select where(Consumer consumer) {
consumer.accept(where.getTemplate());
where.onQuery();
return this;
}
public Select where(T template) {
Where.interceptor.runAnonymous(null, where.getTemplate(), template);
where.onQuery();
return this;
}
public Select where(BiConsumer, T> consumer) {
consumer.accept(this, where.getTemplate());
where.onQuery();
return this;
}
public R getSingleResult() {
where.onQuery();
if (selections.size() == 1) {
getQuery().select((Selection extends T>) selections.get(0));
} else if (!selections.isEmpty()) {
getQuery().multiselect(selections);
} else {
getQuery().select(getFrom());
}
Query query = where.getEntityManager().createQuery(getQuery());
if (maxResults >= 0)
query.setMaxResults(maxResults);
if (firstResult >= 0)
query.setFirstResult(firstResult);
setHints(query);
return (R) query.getSingleResult();
}
public List getResultList() {
where.onQuery();
if (selections.size() == 1) {
getQuery().select((Selection extends T>) selections.get(0));
} else if (!selections.isEmpty()) {
getQuery().multiselect(selections.toArray(new Selection[selections.size()]));
} else {
getQuery().select(getFrom());
}
Query query = where.getEntityManager().createQuery(getQuery());
if (maxResults >= 0)
query.setMaxResults(maxResults);
if (firstResult >= 0)
query.setFirstResult(firstResult);
setHints(query);
return query.getResultList();
}
private void setHints(Query query) {
for (Map.Entry entry : hints.entrySet())
query.setHint(entry.getKey(), entry.getValue());
}
public Path path(Consumer consumer) {
Class entityClass = Interceptor.getTargetClass(where.getTemplate());
AtomicReference ref = new AtomicReference<>();
T t = applyGetter(entityClass, ref::set);
consumer.accept(t);
return ref.get();
}
public Select selectEntity() {
selections.add(getFrom());
return this;
}
public Select select(Function> builder, Consumer consumer) {
Path path = path(consumer);
select(builder.apply(getBuilder()).apply(path));
return this;
}
public Select select(Expression expression) {
selections.add(expression);
return this;
}
public Select select(Runnable runnable) {
Interceptor.setInterceptorHandler(where.getTemplate(), getter(path -> selections.add(path)));
runnable.run();
Interceptor.setInterceptorHandler(where.getTemplate(), where);
return this;
}
public Select select(Consumer consumer) {
Class entityClass = Interceptor.getTargetClass(where.getTemplate());
T t = applyGetter(entityClass, path -> selections.add(path));
consumer.accept(t);
return this;
}
public Select crossJoinManyToOneWhere(Class entityClass, Consumer joinCondition, Consumer consumer) {
return crossJoinManyToOne(entityClass, joinCondition, nestedSelect -> nestedSelect.where(consumer));
}
public Select crossJoinManyToOne(Class entityClass, Consumer joinCondition, BiConsumer, R> consumer) {
return crossJoinManyToOne(entityClass, joinCondition, nestedSelect -> nestedSelect.where(consumer));
}
@SuppressWarnings("squid:S1188")
public Select crossJoinManyToOne(Class entityClass, Consumer joinCondition, Consumer> consumer) {
From jointRoot = getQuery().from(entityClass);
Interceptor.setInterceptorHandler(where.getTemplate(), frame -> {
PropertyDescriptor desc = Reflection.propertyDescriptor(frame.getMethod());
String property = desc.getName();
if (frame.getMethod().equals(desc.getReadMethod())) {
Predicate joinPredicate;
if (getFrom().get(property).getJavaType().equals(jointRoot.getJavaType())) {
joinPredicate = getBuilder().equal(getFrom().get(property), jointRoot);
} else {
EntityType type = (EntityType) jointRoot.getModel();
String parentIdAttribute = type.getId(type.getIdType().getJavaType()).getName();
if (!jointRoot.get(parentIdAttribute).getJavaType().equals(getFrom().get(property).getJavaType())) {
throw new IllegalArgumentException("Type mismatch: cannot join " + type.getName() + "." + parentIdAttribute + " to " +
getFrom().get(property));
}
joinPredicate = getBuilder().equal(jointRoot.get(parentIdAttribute), getFrom().get(property));
}
this.where.getPredicates().add(joinPredicate);
} else {
throw new UnsupportedOperationException(GETTER_MSG);
}
return null;
});
joinCondition.accept(getTemplate());
Interceptor.setInterceptorHandler(where.getTemplate(), where);
Where where = new Where<>(this.where, jointRoot);
Select joinSelect = new Select<>(this, where, jointRoot);
consumer.accept(joinSelect);
return this;
}
public Select crossJoinOneToManyWhere(Class entityClass, Consumer joinCondition, Consumer consumer) {
return crossJoinOneToMany(entityClass, joinCondition, nestedSelect -> nestedSelect.where(consumer));
}
public Select crossJoinOneToMany(Class entityClass, Consumer joinCondition, BiConsumer, R> consumer) {
return crossJoinOneToMany(entityClass, joinCondition, nestedSelect -> nestedSelect.where(consumer));
}
@SuppressWarnings("squid:S1188")
public Select crossJoinOneToMany(Class entityClass, Consumer joinCondition, Consumer> consumer) {
From joinRoot = getQuery().from(entityClass);
R joinTemplate = Handler.interceptor.newInstance(entityClass, frame -> {
PropertyDescriptor desc = Reflection.propertyDescriptor(frame.getMethod());
String property = desc.getName();
if (frame.getMethod().equals(desc.getReadMethod())) {
Predicate joinPredicate;
if (joinRoot.get(property).getJavaType().equals(getFrom().getJavaType())) {
joinPredicate = getBuilder().equal(getFrom(), joinRoot.get(property));
} else {
EntityType type = (EntityType) getFrom().getModel();
String parentIdAttribute = type.getId(type.getIdType().getJavaType()).getName();
if (!getFrom().get(parentIdAttribute).getJavaType().equals(joinRoot.get(property).getJavaType())) {
throw new IllegalArgumentException("Type mismatch: cannot join " + type.getName() + "." + parentIdAttribute + " to " +
joinRoot.get(property));
}
joinPredicate = getBuilder().equal(getFrom().get(parentIdAttribute), joinRoot.get(property));
}
this.where.getPredicates().add(joinPredicate);
} else {
throw new UnsupportedOperationException(GETTER_MSG);
}
return Primitives.defaultValue(desc.getPropertyType());
});
joinCondition.accept(joinTemplate);
Where where = new Where<>(this.where, joinRoot);
Select joinSelect = new Select<>(this, where, joinRoot);
consumer.accept(joinSelect);
return this;
}
public Select leftJoin(Runnable joinCondition, BiConsumer, R> consumer) {
return join(JoinType.LEFT, joinCondition, consumer);
}
public Select leftJoin(Runnable joinCondition, Consumer> consumer ) {
return this.join(JoinType.LEFT, joinCondition, (sel, r) -> consumer.accept(sel));
}
public Select leftJoin(Runnable joinCondition) {
return join(JoinType.LEFT, joinCondition, (sel, r) -> { /* no-op */});
}
public Select join(Runnable joinCondition, BiConsumer, R> consumer) {
return join(JoinType.INNER, joinCondition, consumer);
}
public Select join(Runnable joinCondition, Consumer> consumer ) {
return this.join(JoinType.INNER, joinCondition, (sel, r) -> consumer.accept(sel));
}
public Select join(Runnable joinCondition) {
return join(JoinType.INNER, joinCondition, (sel, r) -> { /* no-op */});
}
protected Select join(JoinType type, Runnable joinCondition, BiConsumer, R> consumer) {
Interceptor.setInterceptorHandler(where.getTemplate(), frame -> {
PropertyDescriptor desc = Reflection.propertyDescriptor(frame.getMethod());
String property = desc.getName();
if (frame.getMethod().equals(desc.getReadMethod())) {
Join join = getFrom().join(property, type);
Where where = new Where<>(this.where, join);
Select joinSelect = new Select<>(this, where, join);
consumer.accept(joinSelect, where.getTemplate());
} else {
throw new UnsupportedOperationException(GETTER_MSG);
}
return Primitives.defaultValue(desc.getPropertyType());
});
joinCondition.run();
Interceptor.setInterceptorHandler(where.getTemplate(), where);
return this;
}
/**
* fetch is used to load detail objects. In most case, you probably want to use leftFetch because if
* the master instance does not have detail instances, it will not be returned whereas for leftFetch the master
* instance is returned.
*
* @param joinCondition runnable to specify the join condition
* @return Select instance
*/
public Select fetch(Runnable joinCondition) {
return fetch(JoinType.INNER, joinCondition);
}
/**
* See description on fetch.
*
* @param joinCondition runnable to specify the join condition
* @return Select instance
*/
public Select leftFetch(Runnable joinCondition) {
return fetch(JoinType.LEFT, joinCondition);
}
protected Select fetch(JoinType type, Runnable joinCondition) {
Interceptor.setInterceptorHandler(where.getTemplate(), frame -> {
PropertyDescriptor desc = Reflection.propertyDescriptor(frame.getMethod());
String property = desc.getName();
if (frame.getMethod().equals(desc.getReadMethod())) {
getFrom().fetch(property, type);
} else {
throw new UnsupportedOperationException(GETTER_MSG);
}
return Primitives.defaultValue(desc.getPropertyType());
});
joinCondition.run();
Interceptor.setInterceptorHandler(where.getTemplate(), where);
return this;
}
public Select setMaxResults(int maxResults) {
this.maxResults = maxResults;
if (parent != null)
parent.setMaxResults(maxResults);
return this;
}
public Select setFirstResult(int firstResult) {
this.firstResult = firstResult;
if (parent != null)
parent.setFirstResult(firstResult);
return this;
}
public void count() {
selections.add(getBuilder().count(getFrom()));
}
public Select asc(Runnable runnable) {
OrderBy orderBy = new OrderBy(where.getEntityManager(), where.getBuilder(), where.getQuery(), getFrom());
Interceptor.setInterceptorHandler(where.getTemplate(), orderBy);
orderBy.desc = false;
orderBy.orderByList = where.orderByList;
runnable.run();
Interceptor.setInterceptorHandler(where.getTemplate(), where);
return this;
}
public Select desc(Runnable runnable) {
OrderBy orderBy = new OrderBy(where.getEntityManager(), where.getBuilder(), where.getQuery(), getFrom());
Interceptor.setInterceptorHandler(where.getTemplate(), orderBy);
orderBy.desc = true;
orderBy.orderByList = where.orderByList;
runnable.run();
Interceptor.setInterceptorHandler(where.getTemplate(), where);
return this;
}
public Expression sum(String attribute) {
return getBuilder().sum(where.getPath().get(attribute));
}
public Expression coalesce(Expression expression, N value) {
CriteriaBuilder.Coalesce coalesce = getBuilder().coalesce();
coalesce.value(expression);
coalesce.value(value);
return coalesce;
}
}