package eu.eudat.queryable.hibernatequeryablelist; import eu.eudat.entities.DataEntity; import eu.eudat.queryable.QueryableList; import eu.eudat.queryable.exceptions.NotSingleResultException; import eu.eudat.queryable.predicates.OrderByPredicate; import eu.eudat.queryable.predicates.SelectPredicate; import eu.eudat.queryable.predicates.SinglePredicate; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import javax.persistence.criteria.*; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public class QueryableHibernateList> implements QueryableList { private EntityManager manager; private CriteriaQuery query; private Class tClass; private Root root; private List predicates = new LinkedList(); private List orderings = new LinkedList<>(); private List fields = new LinkedList<>(); private Integer length; private Integer offset; private Set hints; private String hint; public QueryableHibernateList(EntityManager manager, Class tClass) { this.manager = manager; this.tClass = tClass; } public QueryableHibernateList setManager(EntityManager manager) { this.manager = manager; return this; } public QueryableList withHint(String hint) { this.hint = hint; return this; } public QueryableList setHints(Set hints) { this.hints = hints; return this; } public QueryableHibernateList setEntity(Class type) { CriteriaBuilder builder = this.manager.getCriteriaBuilder(); this.query = builder.createQuery(type); this.root = this.query.from(this.tClass); return this; } public void initiateQueryableList(Class type) { CriteriaBuilder builder = this.manager.getCriteriaBuilder(); this.query = builder.createQuery(type); } @Override public QueryableList skip(Integer offset) { this.offset = offset; return this; } @Override public QueryableList take(Integer length) { this.length = length; return this; } public QueryableList where(SinglePredicate predicate) { this.predicates.add(predicate.applyPredicate(this.manager.getCriteriaBuilder(), this.root)); return this; } public List select(SelectPredicate predicate) { List list = this.toList(); List newlist = new LinkedList(); for (T item : list) { newlist.add(predicate.applySelection(item)); } return newlist; } public QueryableList distinct() { this.query.distinct(true); return this; } public QueryableList orderByAsc(OrderByPredicate predicate) { this.orderings.add(this.manager.getCriteriaBuilder().asc(predicate.applyPredicate(this.root))); return this; } public QueryableList orderByDesc(OrderByPredicate predicate) { this.orderings.add(this.manager.getCriteriaBuilder().desc(predicate.applyPredicate(this.root))); return this; } public Long count() { CriteriaBuilder criteriaBuilder = this.manager.getCriteriaBuilder(); CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); criteriaQuery.select(criteriaBuilder.count(criteriaQuery.from(this.tClass))); criteriaQuery.where(this.predicates.toArray(new Predicate[this.predicates.size()])); return this.manager.createQuery(criteriaQuery).getSingleResult(); } public List toList() { this.query.where(this.predicates.toArray(new Predicate[this.predicates.size()])); if (!this.orderings.isEmpty()) this.query.orderBy(this.orderings); TypedQuery typedQuery = this.manager.createQuery(this.query); if (this.offset != null) typedQuery.setFirstResult(this.offset); if (this.length != null) typedQuery.setMaxResults(this.length); if (this.hint != null && this.hints.contains(hint)) { List ids = typedQuery.getResultList().stream().map(item -> item.getKeys()[0]).collect(Collectors.toList()); if (ids != null && !ids.isEmpty()) typedQuery = queryWithHint(ids); } return typedQuery.getResultList(); } public T getSingle() { Predicate[] array = new Predicate[this.predicates.size()]; this.predicates.toArray(array); this.query.where(array); TypedQuery typedQuery = this.manager.createQuery(this.query); return typedQuery.getSingleResult(); } public T getSingleOrDefault() { Predicate[] array = new Predicate[this.predicates.size()]; this.predicates.toArray(array); this.query.where(array); TypedQuery typedQuery = this.manager.createQuery(this.query); List results = typedQuery.getResultList(); if (results.size() == 0) return null; if (results.size() == 1) return results.get(0); else throw new NotSingleResultException("Query returned more than one items"); } private TypedQuery queryWithHint(List ids) { CriteriaBuilder criteriaBuilder = this.manager.getCriteriaBuilder(); CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(tClass); Root criteriaRoot = criteriaQuery.from(this.tClass); criteriaQuery.where(criteriaRoot.get("id").in(ids)); TypedQuery typedQuery = this.manager.createQuery(criteriaQuery); typedQuery.setHint("javax.persistence.fetchgraph", this.manager.getEntityGraph(this.hint)); return typedQuery; } }