Java tutorial
/* * Copyright 2013 Marcelo Morales me@marcelomorales.name * * 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 name.marcelomorales.siqisiqi.openjpa.impl; import com.google.common.base.Strings; import com.google.common.collect.Lists; import name.marcelomorales.siqisiqi.openjpa.api.OrderBy; import name.marcelomorales.siqisiqi.openjpa.api.OrmFinder; import name.marcelomorales.siqisiqi.openjpa.api.OrmFinderSettings; import name.marcelomorales.siqisiqi.openjpa.api.OrmUtils; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.persistence.OpenJPAEntityManager; import org.apache.openjpa.persistence.OpenJPAPersistence; import org.apache.openjpa.persistence.criteria.ComparisonStyle; import org.apache.openjpa.persistence.criteria.OpenJPACriteriaBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.ejb.TransactionAttribute; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.TypedQuery; import javax.persistence.criteria.*; import javax.persistence.metamodel.Attribute; import java.io.Serializable; import java.util.*; /** * Encapsulates OpenJPA-specific behaviour. * * @author Marcelo Morales */ public class OrmFinderImpl<T, PK extends Serializable> implements OrmFinder<T, PK> { private static final Logger LOGGER = LoggerFactory.getLogger(OrmFinderImpl.class); private final OpenJPAEntityManager entityManager; private final Class<T> persistentClass; private final OrmFinderSettings<T, PK> settings; public OrmFinderImpl(EntityManager entityManager, Class<T> persistentClass, OrmFinderSettings<T, PK> settings) { this.settings = settings; this.entityManager = OpenJPAPersistence.cast(entityManager); this.persistentClass = persistentClass; } @Override @TransactionAttribute public T findByPK(final PK id, final String... fg) { LOGGER.debug("Searching {} id {}, fg {}", new Object[] { persistentClass, id, fg }); if (fg != null) { entityManager.pushFetchPlan(); entityManager.getFetchPlan().addFetchGroups(fg); } T t = entityManager.find(persistentClass, id); if (fg != null) { entityManager.popFetchPlan(); } return t; } @Override @TransactionAttribute public T findCached(final PK id) { LOGGER.debug("Searching {} id id {}, cached", persistentClass, id); return entityManager.findCached(persistentClass, id); } @Override @TransactionAttribute public long countByAttribute(String attributeName, Object attributeValue) { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Long> q = cb.createQuery(Long.class); Root<T> p = q.from(persistentClass); final Expression<Long> count = newCountExpression(cb, p); q.select(count); q.where(cb.equal(p.get(attributeName), attributeValue)); try { return entityManager.createQuery(q).getSingleResult(); } catch (NoResultException e) { return 0; } } @Override @TransactionAttribute public List<T> findByAttribute(String attributeName, Object attributeValue, long first, long count, String... fg) { LOGGER.debug("Searching {} bu attribute {} : {}, fg {}", new Object[] { persistentClass, attributeName, attributeValue, fg }); if (fg != null) { entityManager.pushFetchPlan(); entityManager.getFetchPlan().addFetchGroups(fg); } CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<T> q = cb.createQuery(persistentClass); Root<T> p = q.from(persistentClass); q.where(cb.equal(p.get(attributeName), attributeValue)); TypedQuery<T> query = entityManager.createQuery(q); OrmUtils.firstCount(query, first, count); List<T> resultList = query.getResultList(); if (fg != null) { entityManager.popFetchPlan(); } return resultList; } @Override @TransactionAttribute public long countByFullTexts(final String terms) { LOGGER.debug("counting by text {} terms {}", persistentClass, terms); if (settings.returnsNullIfTermsAreNull() && Strings.isNullOrEmpty(terms)) { return 0; } CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Long> q = cb.createQuery(Long.class); Root<T> p = q.from(persistentClass); final Expression<Long> count = newCountExpression(cb, p); q.select(count); q.where(newFullTextPredicate(cb, p, terms)); try { return entityManager.createQuery(q).getSingleResult(); } catch (NoResultException e) { return 0; } } @Override @TransactionAttribute public List<T> findByFullTexts(final String terms, final OrderBy<T> orders, final long first, final long count, final String... fg) { LOGGER.debug("searching by text {} terms {}, fg {}", new Object[] { persistentClass, terms, fg }); if (settings.returnsNullIfTermsAreNull() && Strings.isNullOrEmpty(terms)) { return Collections.emptyList(); } if (fg != null) { entityManager.pushFetchPlan(); entityManager.getFetchPlan().addFetchGroups(fg); } CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<T> q = cb.createQuery(persistentClass); Root<T> p = q.from(persistentClass); q.where(newFullTextPredicate(cb, p, terms)); if (orders != null) { List<Order> orderList = orders.orders(cb, p); if (orderList != null && !orderList.isEmpty()) { q.orderBy(orderList); } } TypedQuery<T> query = entityManager.createQuery(q); OrmUtils.firstCount(query, first, count); List<T> resultList = query.getResultList(); if (fg != null) { entityManager.popFetchPlan(); } return resultList; } @Override @TransactionAttribute public long countByExample(final T example, final T example2) { OpenJPACriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Long> q = cb.createQuery(Long.class); Root<T> from = q.from(persistentClass); final Expression<Long> count = newCountExpression(cb, from); q.select(count); q.where(newQbePredicates(cb, from, example, example2)); TypedQuery<Long> query = entityManager.createQuery(q); try { return query.getSingleResult(); } catch (NoResultException e) { return 0; } } @Override @TransactionAttribute public List<T> findByExample(final T example, final T example2, final OrderBy<T> sortParam, final long first, final long count, final String... fg) { if (fg != null) { entityManager.pushFetchPlan(); entityManager.getFetchPlan().addFetchGroups(fg); } OpenJPACriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<T> q = cb.createQuery(persistentClass); Root<T> from = q.from(persistentClass); q.where(newQbePredicates(cb, from, example, example2)); if (sortParam != null) { List<Order> orderList = sortParam.orders(cb, from); if (orderList != null && !orderList.isEmpty()) { q.orderBy(orderList); } } TypedQuery<T> query = entityManager.createQuery(q); OrmUtils.firstCount(query, first, count); List<T> resultList = query.getResultList(); if (fg != null) { entityManager.popFetchPlan(); } return resultList; } protected Predicate[] newQBEPredicates(OpenJPACriteriaBuilder cb, Root<T> from, T example, T example2, ComparisonStyle style) { Attribute<?, ?>[] betweens = settings.betweens(from, persistentClass); ArrayList<Predicate> predicates = Lists.newArrayListWithExpectedSize(betweens.length + 1); predicates.add(cb.qbe(from, example, style, betweens)); if (betweens.length > 0) { for (Attribute<?, ?> between : betweens) { String name = between.getName(); Path<Comparable> objectPath = from.get(name); Comparable propertyValue1 = OrmUtils.get(example, name); Comparable propertyValue2 = OrmUtils.get(example2, name); predicates.add(cb.between(objectPath, propertyValue1, propertyValue2)); } } return predicates.toArray(new Predicate[predicates.size()]); } protected Expression<Long> newCountExpression(CriteriaBuilder cb, Root<T> from) { final Path<PK> countPath = settings.countPath(from, persistentClass); if (countPath == null) { throw new IllegalStateException("Implements countPath en " + persistentClass); } return cb.count(countPath); } protected Predicate newFullTextPredicate(CriteriaBuilder cb, Root<T> p, String terms) { LinkedList<Predicate> predicatesOr = Lists.newLinkedList(); Iterable<Path<String>> fullTexts = settings.getFullTexts(p, persistentClass); if (fullTexts != null) { for (Path<String> x : fullTexts) { StringTokenizer tokenizer = new StringTokenizer(terms, " \t\n\r\f,.;:/"); LinkedList<Predicate> predicatesAnd = Lists.newLinkedList(); while (tokenizer.hasMoreTokens()) { String token = "%" + tokenizer.nextToken() + "%"; predicatesAnd.add(cb.like(cb.lower(x), StringUtils.lowerCase(token))); } predicatesOr.add(cb.and(predicatesAnd.toArray(new Predicate[predicatesAnd.size()]))); } } final Predicate[] restrictions = predicatesOr.toArray(new Predicate[predicatesOr.size()]); return cb.or(restrictions); } protected Predicate[] newQbePredicates(OpenJPACriteriaBuilder cb, Root<T> from, T example, T example2) { if (example == null) { return new Predicate[0]; } else { if (example2 == null) { final Predicate qbe = cb.qbe(from, example, settings.getComparisonStyle()); return new Predicate[] { qbe }; } else { return newQBEPredicates(cb, from, example, example2, settings.getComparisonStyle()); } } } }