Author: bleny Date: 2013-11-22 15:24:00 +0100 (Fri, 22 Nov 2013) New Revision: 2876 Url: http://nuiton.org/projects/topia/repository/revisions/2876 Log: fixes #2915 introduce QueryMissingOrderException, in TopiaQueryBuilderRunQueryStep add throws clauses in signature Added: trunk/topia-persistence/src/main/java/org/nuiton/topia/QueryMissingOrderException.java Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/AbstractTopiaDao.java trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaQueryBuilderRunQueryStep.java Added: trunk/topia-persistence/src/main/java/org/nuiton/topia/QueryMissingOrderException.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/QueryMissingOrderException.java (rev 0) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/QueryMissingOrderException.java 2013-11-22 14:24:00 UTC (rev 2876) @@ -0,0 +1,24 @@ +package org.nuiton.topia; + +import java.util.Map; + +/** + * If you get this exception, it means that you asked topia + * to make an operation that need a deterministic way to sort the + * result but you didn't defined such query. + * + * To fix you issue, you may use another API call (maybe user findAny instead + * of findFirst) or change your query by adding an order by clause. A quick and + * easy fix would be to just use "order by topiaId". + * + * @since 3.0 + */ +public class QueryMissingOrderException extends TopiaQueryException { + + protected static final String MESSAGE = "given query needs an order by clause since the API call you use need the results sorting to be deterministic"; + + public QueryMissingOrderException(String hql, Map<String, Object> hqlParameters) { + super(MESSAGE, hql, hqlParameters); + } + +} Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/AbstractTopiaDao.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/AbstractTopiaDao.java 2013-11-18 14:44:43 UTC (rev 2875) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/AbstractTopiaDao.java 2013-11-22 14:24:00 UTC (rev 2876) @@ -47,6 +47,7 @@ import org.apache.commons.logging.LogFactory; import org.hibernate.HibernateException; import org.hibernate.metadata.ClassMetadata; +import org.nuiton.topia.QueryMissingOrderException; import org.nuiton.topia.TopiaDaoSupplier; import org.nuiton.topia.TopiaException; import org.nuiton.topia.TopiaHibernateSupport; @@ -413,12 +414,12 @@ return result; } - protected E findUnique(String hql, Map<String, Object> hqlParameters) { + protected E findUnique(String hql, Map<String, Object> hqlParameters) throws TopiaNoResultException { E result = findUnique(hql, hqlParameters, getEntityClass()); return result; } - protected E findUniqueOrNull(String hql, Map<String, Object> hqlParameters) { + protected E findUniqueOrNull(String hql, Map<String, Object> hqlParameters) throws TopiaNonUniqueResultException { E result = findUniqueOrNull(hql, hqlParameters, getEntityClass()); return result; } @@ -428,22 +429,22 @@ return result; } - protected E findFirst(String hql, Map<String, Object> hqlParameters) { + protected E findFirst(String hql, Map<String, Object> hqlParameters) throws TopiaNoResultException { E result = findFirst(hql, hqlParameters, getEntityClass()); return result; } - protected E findFirstOrNull(String hql, Map<String, Object> hqlParameters) { + protected E findFirstOrNull(String hql, Map<String, Object> hqlParameters) throws QueryMissingOrderException { E result = findFirstOrNull(hql, hqlParameters, getEntityClass()); return result; } - protected Optional<E> tryFindFirst(String hql, Map<String, Object> hqlParameters) { + protected Optional<E> tryFindFirst(String hql, Map<String, Object> hqlParameters) throws QueryMissingOrderException { Optional<E> result = tryFindFirst(hql, hqlParameters, getEntityClass()); return result; } - protected E findAny(String hql, Map<String, Object> hqlParameters) { + protected E findAny(String hql, Map<String, Object> hqlParameters) throws TopiaNoResultException { E result = findAny(hql, hqlParameters, getEntityClass()); return result; } @@ -458,7 +459,7 @@ return result; } - protected <R> R findUnique(String hql, Map<String, Object> hqlParameters, Class<R> type) { + protected <R> R findUnique(String hql, Map<String, Object> hqlParameters, Class<R> type) throws TopiaNoResultException, TopiaNonUniqueResultException { R result = findUniqueOrNull(hql, hqlParameters, type); if (result == null) { throw new TopiaNoResultException(hql, hqlParameters); @@ -466,13 +467,13 @@ return result; } - protected <R> Optional<R> tryFindUnique(String hql, Map<String, Object> hqlParameters, Class<R> type) { + protected <R> Optional<R> tryFindUnique(String hql, Map<String, Object> hqlParameters, Class<R> type) throws TopiaNonUniqueResultException { R uniqueOrNull = findUniqueOrNull(hql, hqlParameters, type); Optional<R> result = Optional.fromNullable(uniqueOrNull); return result; } - protected <R> R findUniqueOrNull(String hql, Map<String, Object> hqlParameters, Class<R> type) { + protected <R> R findUniqueOrNull(String hql, Map<String, Object> hqlParameters, Class<R> type) throws TopiaNonUniqueResultException { List<R> results = findAll(hql, hqlParameters, type, 0, 1); // If there is more than 1 result, throw an exception if (results.size() > 1) { @@ -483,7 +484,7 @@ return result; } - protected <R> R findFirst(String hql, Map<String, Object> hqlParameters, Class<R> type) { + protected <R> R findFirst(String hql, Map<String, Object> hqlParameters, Class<R> type) throws QueryMissingOrderException { R result = findFirstOrNull(hql, hqlParameters, type); if (result == null) { throw new TopiaNoResultException(hql, hqlParameters); @@ -491,19 +492,21 @@ return result; } - protected <R> Optional<R> tryFindFirst(String hql, Map<String, Object> hqlParameters, Class<R> type) { + protected <R> Optional<R> tryFindFirst(String hql, Map<String, Object> hqlParameters, Class<R> type) throws QueryMissingOrderException { R firstOrNull = findFirstOrNull(hql, hqlParameters, type); Optional<R> result = Optional.fromNullable(firstOrNull); return result; } - protected <R> R findFirstOrNull(String hql, Map<String, Object> hqlParameters, Class<R> type) { - Preconditions.checkArgument(hql.toLowerCase().contains("order by")); + protected <R> R findFirstOrNull(String hql, Map<String, Object> hqlParameters, Class<R> type) throws QueryMissingOrderException { + if ( ! hql.toLowerCase().contains("order by")) { + throw new QueryMissingOrderException(hql, hqlParameters); + } R result = findAnyOrNull(hql, hqlParameters, type); return result; } - protected <R> R findAny(String hql, Map<String, Object> hqlParameters, Class<R> type) { + protected <R> R findAny(String hql, Map<String, Object> hqlParameters, Class<R> type) throws TopiaNoResultException { R result = findAnyOrNull(hql, hqlParameters, type); if (result == null) { throw new TopiaNoResultException(hql, hqlParameters); @@ -712,9 +715,7 @@ String hql2 = hql.toLowerCase(); int i = hql2.indexOf("order by"); if (i == -1) { - throw new IllegalStateException( - "must have a *order by* in hql, " + - "but did not find it in " + hql); + throw new QueryMissingOrderException(hql, params); } // get the count (removing the order-by) @@ -969,37 +970,37 @@ } @Override - public E findUnique() { + public E findUnique() throws TopiaNoResultException, TopiaNonUniqueResultException { return topiaDAO.findUnique(hql, hqlParameters); } @Override - public E findUniqueOrNull() { + public E findUniqueOrNull() throws TopiaNonUniqueResultException { return topiaDAO.findUniqueOrNull(hql, hqlParameters); } @Override - public Optional<E> tryFindUnique() { + public Optional<E> tryFindUnique() throws TopiaNonUniqueResultException { return topiaDAO.tryFindUnique(hql, hqlParameters); } @Override - public E findFirst() { + public E findFirst() throws QueryMissingOrderException, TopiaNoResultException { return topiaDAO.findFirst(hql, hqlParameters); } @Override - public E findFirstOrNull() { + public E findFirstOrNull() throws QueryMissingOrderException { return topiaDAO.findFirstOrNull(hql, hqlParameters); } @Override - public Optional<E> tryFindFirst() { + public Optional<E> tryFindFirst() throws QueryMissingOrderException { return topiaDAO.tryFindFirst(hql, hqlParameters); } @Override - public E findAny() { + public E findAny() throws TopiaNoResultException { return topiaDAO.findAny(hql, hqlParameters); } Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaQueryBuilderRunQueryStep.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaQueryBuilderRunQueryStep.java 2013-11-18 14:44:43 UTC (rev 2875) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaQueryBuilderRunQueryStep.java 2013-11-22 14:24:00 UTC (rev 2876) @@ -25,45 +25,90 @@ */ import com.google.common.base.Optional; +import org.nuiton.topia.QueryMissingOrderException; +import org.nuiton.topia.TopiaNoResultException; +import org.nuiton.topia.TopiaNonUniqueResultException; import java.util.List; /** - * @author bleny + * This interface represents different common operations that + * a user may do after a query is defined (using the + * {@link org.nuiton.topia.persistence.TopiaQueryBuilderAddCriteriaStep}) + * + * There are different methods according to the supposed existence or uniqueness + * of the result. Also some methods may be used only if order is defined in query. + * + * Some methods return an {@link Optional}, but since it's not yet available in JDK, + * we use Guava's. If you don't want your project to require Guava dependency, we + * provide equivalent method named XXXOrNull() for the same purpose. + * + * @since 3.0 */ public interface TopiaQueryBuilderRunQueryStep<E extends TopiaEntity> { + /** + * @return true if the query returns at least one element + */ boolean exists(); + /** + * This method is equivalent as calling {@link java.util.Collection#size()} + * after doing a {@link #findAll()} but it may be faster. + * + * @return the number of that the query would have returned, if executed + */ long count(); - E findUnique(); + E findUnique() throws TopiaNoResultException, TopiaNonUniqueResultException; - E findUniqueOrNull(); + E findUniqueOrNull() throws TopiaNonUniqueResultException; - Optional<E> tryFindUnique(); + Optional<E> tryFindUnique() throws TopiaNonUniqueResultException; /** - * Find first entity for query. - * - * Warning: Query must be ordered for this to run. - * - * @return first entity + * Get the first element of the non-empty result set. + * + * @return the first value from the set of result, + * according to given order. Returned value + * can't be null + * @throws QueryMissingOrderException if you the query + * misses an order clause */ - E findFirst(); + E findFirst() throws QueryMissingOrderException, TopiaNoResultException; /** - * Find first entity for query (or null if no entity is found). - * - * Warning: Query must be ordered for this to run. - * - * @return first entity (or null if no entity is found) + * Get the first element of the result set or null if + * query result was empty. + * + * This method duplicates {@link #tryFindFirst()} + * but allows you to prevent using Guava in you project. + * + * @return the first value from the set of result, + * according to given order, or null of result + * set for given query was empty + * @throws QueryMissingOrderException if you the query + * misses an order clause */ - E findFirstOrNull(); + E findFirstOrNull() throws QueryMissingOrderException; - Optional<E> tryFindFirst(); + /** + * Get the first element of the result set. + * + * This method duplicates {@link #tryFindFirst()} + * but allows you to prevent using Guava in you project. + * + * If the call must return a result, prefer {@link #findFirst()} + * + * @return the first value from the set of result, + * according to given order. It's an optional + * because the query may return no result. + * @throws QueryMissingOrderException if you the query + * misses an order clause + */ + Optional<E> tryFindFirst() throws QueryMissingOrderException; - E findAny(); + E findAny() throws TopiaNoResultException; E findAnyOrNull();
participants (1)
-
bleny@users.nuiton.org