This is an automated email from the git hooks/post-receive script. New commit to branch feature/orderBy in repository topia. See http://git.nuiton.org/topia.git commit c6d078244d6fc5f732a1001acce8f7bd890904c9 Author: Arnaud Thimel <thimel@codelutin.com> Date: Fri Sep 12 11:59:31 2014 +0200 refs #3508 TopiaJpaSupport#find(...) now fails if no order is specified --- .../topia/it/legacy/TopiaJpaSupportTest.java | 39 ++++++++++---------- .../persistence/internal/AbstractTopiaDao.java | 18 ++++------ .../internal/support/HibernateTopiaJpaSupport.java | 42 ++++++++++++++++++---- .../topia/persistence/support/TopiaJpaSupport.java | 22 ++++++++++-- 4 files changed, 82 insertions(+), 39 deletions(-) diff --git a/topia-it/src/test/java/org/nuiton/topia/it/legacy/TopiaJpaSupportTest.java b/topia-it/src/test/java/org/nuiton/topia/it/legacy/TopiaJpaSupportTest.java index 9021436..48250df 100644 --- a/topia-it/src/test/java/org/nuiton/topia/it/legacy/TopiaJpaSupportTest.java +++ b/topia-it/src/test/java/org/nuiton/topia/it/legacy/TopiaJpaSupportTest.java @@ -59,9 +59,9 @@ public class TopiaJpaSupportTest { protected TopiaJpaSupport jpaSupport; - protected AddressTopiaDao addressDAO; + protected AddressTopiaDao addressDao; - protected PersonneTopiaDao personneDAO; + protected PersonneTopiaDao personneDao; protected Address address; @@ -72,19 +72,19 @@ public class TopiaJpaSupportTest { Field field = FieldUtils.getField(AbstractTopiaPersistenceContext.class, "jpaSupport", true); jpaSupport = (TopiaJpaSupport) field.get(persistenceContext); - personneDAO = persistenceContext.getPersonneDao(); - addressDAO = persistenceContext.getAddressDao(); + personneDao = persistenceContext.getPersonneDao(); + addressDao = persistenceContext.getAddressDao(); - address = addressDAO.create( + address = addressDao.create( Address.PROPERTY_ADRESS, "17 rue de la Pote Gellée, 44200 NANTES"); - personneDAO.create( + personneDao.create( Personne.PROPERTY_NAME, "Arnaud", Personne.PROPERTY_GENDER, Gender.MALE); - personneDAO.create( + personneDao.create( Personne.PROPERTY_NAME, "Charlotte", Personne.PROPERTY_GENDER, Gender.FEMALE); - personneDAO.create( + personneDao.create( Personne.PROPERTY_NAME, "Hortense", Personne.PROPERTY_GENDER, Gender.FEMALE); persistenceContext.commit(); @@ -92,19 +92,19 @@ public class TopiaJpaSupportTest { @Test public void testFindDAO() throws TopiaException { - Assert.assertEquals(3, personneDAO.count()); + Assert.assertEquals(3, personneDao.count()); - Assert.assertEquals(2, personneDAO.forGenderEquals(Gender.FEMALE).count()); - Assert.assertNotNull(personneDAO.forGenderEquals(Gender.FEMALE).findAnyOrNull()); - Assert.assertNotNull(personneDAO.forGenderEquals(Gender.MALE).findAnyOrNull()); - Assert.assertNull(personneDAO.forGenderEquals(null).findAnyOrNull()); + Assert.assertEquals(2, personneDao.forGenderEquals(Gender.FEMALE).count()); + Assert.assertNotNull(personneDao.forGenderEquals(Gender.FEMALE).findAnyOrNull()); + Assert.assertNotNull(personneDao.forGenderEquals(Gender.MALE).findAnyOrNull()); + Assert.assertNull(personneDao.forGenderEquals(null).findAnyOrNull()); - Assert.assertEquals(0, personneDAO.forNameEquals("nobody").count()); + Assert.assertEquals(0, personneDao.forNameEquals("nobody").count()); } @Test public void testFindAll() throws TopiaException { - Assert.assertEquals(3, personneDAO.count()); + Assert.assertEquals(3, personneDao.count()); String query = "from " + Personne.class.getName() + " where " + Personne.PROPERTY_GENDER + "=:g"; @@ -132,10 +132,11 @@ public class TopiaJpaSupportTest { @Test public void testFind() throws TopiaException { - Assert.assertEquals(3, personneDAO.count()); + Assert.assertEquals(3, personneDao.count()); String query = "from " + Personne.class.getName() + - " where " + Personne.PROPERTY_GENDER + "=:g"; + " where " + Personne.PROPERTY_GENDER + "=:g" + + " order by id "; Map<String, Object> args = Maps.newHashMap(); @@ -160,7 +161,7 @@ public class TopiaJpaSupportTest { @Test public void testFindUnique() throws TopiaException { - Assert.assertEquals(3, personneDAO.count()); + Assert.assertEquals(3, personneDao.count()); String query = "from " + Personne.class.getName() + " where " + Personne.PROPERTY_GENDER + "=:g"; @@ -179,7 +180,7 @@ public class TopiaJpaSupportTest { @Test(expected = TopiaException.class) public void testFindUniqueOutOfBounds() throws TopiaException { - Assert.assertEquals(3, personneDAO.count()); + Assert.assertEquals(3, personneDao.count()); String query = "from " + Personne.class.getName() + " where " + Personne.PROPERTY_GENDER + "=:g"; diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/AbstractTopiaDao.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/AbstractTopiaDao.java index 1265347..4071931 100644 --- a/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/AbstractTopiaDao.java +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/AbstractTopiaDao.java @@ -461,8 +461,9 @@ public abstract class AbstractTopiaDao<E extends TopiaEntity> implements TopiaDa } protected boolean exists(String hql, Map<String, Object> hqlParameters) { - List<E> entities = topiaJpaSupport.find(hql, 0, 0, hqlParameters); - boolean result = !entities.isEmpty(); + // TODO AThimel 12/09/14 Avoid loading entity, just count the results + E entity = topiaJpaSupport.findAny(hql, hqlParameters); + boolean result = entity != null; return result; } @@ -487,13 +488,9 @@ public abstract class AbstractTopiaDao<E extends TopiaEntity> implements TopiaDa } protected <O> O findUniqueOrNull(String hql, Map<String, Object> hqlParameters) throws TopiaNonUniqueResultException { - List<O> results = find(hql, hqlParameters, 0, 1); - // If there is more than 1 result, throw an exception - if (results.size() > 1) { - throw new TopiaNonUniqueResultException(hql, hqlParameters); - } - // otherwise return the first one, or null - O result = Iterables.getOnlyElement(results, null); + Preconditions.checkNotNull(hql); + Preconditions.checkNotNull(hqlParameters); + O result = topiaJpaSupport.findUnique(hql, hqlParameters); return result; } @@ -543,8 +540,7 @@ public abstract class AbstractTopiaDao<E extends TopiaEntity> implements TopiaDa protected <O> O findAnyOrNull(String hql, Map<String, Object> hqlParameters) { Preconditions.checkNotNull(hql); Preconditions.checkNotNull(hqlParameters); - List<O> results = find(hql, hqlParameters, 0, 0); - O result = Iterables.getOnlyElement(results, null); + O result = topiaJpaSupport.findAny(hql, hqlParameters); return result; } diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/support/HibernateTopiaJpaSupport.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/support/HibernateTopiaJpaSupport.java index d024c5a..d2b79d7 100644 --- a/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/support/HibernateTopiaJpaSupport.java +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/support/HibernateTopiaJpaSupport.java @@ -25,13 +25,17 @@ package org.nuiton.topia.persistence.internal.support; */ import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.FlushMode; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.loader.MultipleBagFetchException; +import org.nuiton.topia.persistence.QueryMissingOrderException; import org.nuiton.topia.persistence.TopiaException; +import org.nuiton.topia.persistence.TopiaNonUniqueResultException; import org.nuiton.topia.persistence.TopiaQueryException; import org.nuiton.topia.persistence.support.TopiaHibernateSupport; import org.nuiton.topia.persistence.support.TopiaJpaSupport; @@ -147,28 +151,52 @@ public class HibernateTopiaJpaSupport implements TopiaJpaSupport { } @Override + public <T> T findAny(String jpaql, Map<String, Object> parameters) { + + // Execute query, and ask for one result only + List<T> results = find0(jpaql, 0, 0, parameters); + + // Return it or null + T result = Iterables.getOnlyElement(results, null); + return result; + } + + @Override public <T> T findUnique(String jpaql, Map<String, Object> parameters) { // Execute query, and ask for up to 2 results only - List<T> results = find(jpaql, 0, 1, parameters); + List<T> results = find0(jpaql, 0, 1, parameters); // If there is more than 1 result, throw an exception if (results.size() > 1) { String message = String.format( "Query '%s' returns more than 1 unique result", jpaql); - throw new TopiaException(message); + throw new TopiaNonUniqueResultException(message, parameters); } // otherwise return the first one, or null - T result = null; - if (!results.isEmpty()) { - result = results.get(0); - } + T result = Iterables.getOnlyElement(results, null); return result; } + // FIXME AThimel 11/09/14 This method duplicates org.nuiton.topia.persistence.internal.AbstractTopiaDao.hqlContainsOrderBy() + protected boolean hqlContainsOrderBy(String hql) { + return hql.toLowerCase().contains("order by"); + } + @Override - public <T> List<T> find(String jpaql, int startIndex, int endIndex, Map<String, Object> parameters) { + public <T> List<T> find(String jpaql, int startIndex, int endIndex, Map<String, Object> parameters) + throws QueryMissingOrderException { + + if (!hqlContainsOrderBy(jpaql)) { + throw new QueryMissingOrderException(jpaql, parameters); + } + + List<T> result = find0(jpaql, startIndex, endIndex, parameters); + return result; + } + + protected <T> List<T> find0(String jpaql, int startIndex, int endIndex, Map<String, Object> parameters) { try { Query query = prepareQuery(jpaql, parameters); diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/support/TopiaJpaSupport.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/support/TopiaJpaSupport.java index 26f2f9b..eacea98 100644 --- a/topia-persistence/src/main/java/org/nuiton/topia/persistence/support/TopiaJpaSupport.java +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/support/TopiaJpaSupport.java @@ -27,6 +27,8 @@ package org.nuiton.topia.persistence.support; import java.util.List; import java.util.Map; +import org.nuiton.topia.persistence.QueryMissingOrderException; + /** * This API provides methods to use persistence using JPA queries * @@ -62,14 +64,30 @@ public interface TopiaJpaSupport { * @param endIndex last index of entity to return * @param parameters a map which keys are the attribute names and values are the attributes expected values * @return The result list + * @throws QueryMissingOrderException if no order by clause is specified */ <T> List<T> find(String jpaql, int startIndex, int endIndex, - Map<String, Object> parameters); + Map<String, Object> parameters) + throws QueryMissingOrderException; + + /** + * Allow to do some JPA-QL query and return a single result. If nothing is + * found by the query, will return null. + * <p/> + * WARNING : Depending on the registered service, this method may not + * support something else than queries on TopiaEntity + * + * @param jpaql the JPA-QL query + * @param parameters a map which keys are the attribute names and values are the attributes expected values + * @return The result instance or null + */ + <T> T findAny(String jpaql, + Map<String, Object> parameters); /** - * Allow to do some JPA-QL query and return an unique result. If nothing if + * Allow to do some JPA-QL query and return an unique result. If nothing is * found by the query, will return null. If more than one result is found, * will throw an exception. * <p/> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.