branch feature/658_use_hibernate_streaming created (now b5d7179e)
This is an automated email from the git hooks/post-receive script. New change to branch feature/658_use_hibernate_streaming in repository topia. See https://gitlab.nuiton.org/nuiton/topia.git at b5d7179e Enable streaming results This branch includes the following new commits: new b5d7179e Enable streaming results The 1 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit b5d7179e6b94cecddbc9f54004821435a8f5bc46 Author: Brendan Le Ny <bleny@codelutin.com> Date: Mon Jan 8 14:59:55 2018 +0100 Enable streaming results Introduce both: - TopiaQueryBuilderRunQueryStep#stream as a public API - AbstractTopiaDao#stream as a protected helper in DAO implementations https://gitlab.nuiton.org/nuiton/topia/issues/658 -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/658_use_hibernate_streaming in repository topia. See https://gitlab.nuiton.org/nuiton/topia.git commit b5d7179e6b94cecddbc9f54004821435a8f5bc46 Author: Brendan Le Ny <bleny@codelutin.com> Date: Mon Jan 8 14:59:55 2018 +0100 Enable streaming results Introduce both: - TopiaQueryBuilderRunQueryStep#stream as a public API - AbstractTopiaDao#stream as a protected helper in DAO implementations https://gitlab.nuiton.org/nuiton/topia/issues/658 --- .../topia/it/legacy/TopiaJpaSupportTest.java | 32 +++++++++++++++ .../persistence/TopiaQueryBuilderRunQueryStep.java | 12 ++++++ .../persistence/internal/AbstractTopiaDao.java | 25 ++++++++++++ .../internal/support/HibernateTopiaJpaSupport.java | 47 +++++++++++++++++++++- .../topia/persistence/support/TopiaJpaSupport.java | 13 ++++++ 5 files changed, 127 insertions(+), 2 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 7c5857aa..6c88259a 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 @@ -24,6 +24,8 @@ package org.nuiton.topia.it.legacy; * #L% */ +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import org.apache.commons.lang3.reflect.FieldUtils; import org.junit.Assert; @@ -43,6 +45,8 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Tests the TopiaContext#find|findAll|findUnique methods @@ -130,6 +134,34 @@ public class TopiaJpaSupportTest { } @Test + public void testStream() { + Preconditions.checkState(personneDao.count() == 3); + + String query = "from " + Personne.class.getName() + + " where " + Personne.PROPERTY_GENDER + "=:g"; + try (Stream<Personne> stream = jpaSupport.stream(query, ImmutableMap.of("g", Gender.FEMALE))) { + List females = stream.collect(Collectors.toList()); + Assert.assertEquals(2, females.size()); + } + + try (Stream<Personne> stream = jpaSupport.stream(query, ImmutableMap.of("g", Gender.MALE))) { + List males = stream.collect(Collectors.toList()); + Assert.assertEquals(1, males.size()); + } + + try (Stream<Personne> stream = jpaSupport.stream("from " + Personne.class.getName(), ImmutableMap.of())) { + List all = stream.collect(Collectors.toList()); + Assert.assertEquals(3, all.size()); + } + + try (Stream<Personne> stream = jpaSupport.stream("from " + Personne.class.getName() + + " where " + Personne.PROPERTY_NAME + "=:pax", ImmutableMap.of("pax", "nobody"))) { + List none = stream.collect(Collectors.toList()); + Assert.assertEquals(0, none.size()); + } + } + + @Test public void testFind() throws TopiaException { Assert.assertEquals(3, personneDao.count()); diff --git a/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaQueryBuilderRunQueryStep.java b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaQueryBuilderRunQueryStep.java index 26aef9c8..e6e9386e 100644 --- a/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaQueryBuilderRunQueryStep.java +++ b/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaQueryBuilderRunQueryStep.java @@ -29,6 +29,7 @@ import org.nuiton.util.pagination.PaginationParameter; import org.nuiton.util.pagination.PaginationResult; import java.util.List; +import java.util.stream.Stream; /** * This interface represents different common operations that a user may do after a query is defined (using the @@ -127,6 +128,17 @@ public interface TopiaQueryBuilderRunQueryStep<E extends TopiaEntity> List<E> findAll(); /** + * Like {@link #findAll()} but getting a stream that may lazily fetch data. + * + * Actual behavior rely on implementation. + * + * Caller should {@link Stream#close()} the stream. + * + * @since 3.4 + */ + Stream<E> stream(); + + /** * Get all the elements in a lazy loading list. The entities will be loaded gradually when the returned Iterable is * iterated. * 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 7f44b5da..8974c3bf 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 @@ -73,6 +73,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; +import java.util.stream.Stream; /** * <p> @@ -567,6 +568,20 @@ public abstract class AbstractTopiaDao<E extends TopiaEntity> implements TopiaDa return result; } + protected <O> Stream<O> stream(String hql) { + Preconditions.checkNotNull(hql); + Map<String, Object> hqlParameters = Collections.emptyMap(); + Stream<O> result = stream(hql, hqlParameters); + return result; + } + + protected <O> Stream<O> stream(String hql, Map<String, Object> hqlParameters) { + Preconditions.checkNotNull(hql); + Preconditions.checkNotNull(hqlParameters); + Stream<O> result = topiaJpaSupport.stream(hql, hqlParameters); + return result; + } + protected <O> List<O> find(String hql, int startIndex, int endIndex) { Preconditions.checkNotNull(hql); Map<String, Object> hqlParameters = Collections.emptyMap(); @@ -1030,6 +1045,11 @@ public abstract class AbstractTopiaDao<E extends TopiaEntity> implements TopiaDa } @Override + public Stream<E> stream() { + return getNextStep().stream(); + } + + @Override public List<E> find(int startIndex, int endIndex) { return getNextStep().find(startIndex, endIndex); } @@ -1199,6 +1219,11 @@ public abstract class AbstractTopiaDao<E extends TopiaEntity> implements TopiaDa } @Override + public Stream<E> stream() { + return topiaDao.stream(hql, hqlParameters); + } + + @Override public Iterable<E> findAllLazy() { return topiaDao.findAllLazy(hql + (fromHql || withOrderByClause ? "" : " ORDER BY id "), hqlParameters); } 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 b5d6b3f0..3ea2ac25 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 @@ -26,7 +26,6 @@ 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; @@ -41,8 +40,11 @@ import org.nuiton.topia.persistence.support.TopiaHibernateSupport; import org.nuiton.topia.persistence.support.TopiaJpaSupport; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Stream; /** * This class is the Hibernate implementation of TopiaJpaSupport. It realizes the bridge between the JPA specification @@ -127,7 +129,7 @@ public class HibernateTopiaJpaSupport implements TopiaJpaSupport { Query query = prepareQuery(jpaql, parameters); List result = query.list(); - result = firesSupport.fireEntitiesLoad(this, result); + result = firesSupport.fireEntitiesLoad(this, result); // FIXME brendan 08/01/18 unchecked assignment warn is legit: we can't be sure it topia entities, it may be any object return result; } catch (MultipleBagFetchException mbfe) { throw new TopiaQueryException( @@ -150,6 +152,47 @@ public class HibernateTopiaJpaSupport implements TopiaJpaSupport { } } + /** + * Like {@link #findAll(String, Map)} but getting a stream that may lazily fetch data. + * + * Actual behavior rely on JPA implementation. + * + * According to {@link Query#stream()}, caller should {@link Stream#close()} the stream. + * + * @since 3.4 + */ + @Override + public <T> Stream<T> stream(String jpaql, Map<String, Object> parameters) { + try { + Query query = prepareQuery(jpaql, parameters); + + Stream result = query.stream(); + Consumer<T> consumer = row -> { + List singleton = Collections.singletonList(row); + firesSupport.fireEntitiesLoad(this, singleton); // FIXME brendan 08/01/18 unchecked assignment warn is legit: we can't be sure it topia entities, it may be any object + }; + return result.peek(consumer); + } catch (MultipleBagFetchException mbfe) { + throw new TopiaQueryException( + "unable to fetch multiple bags during " + mbfe.getBagRoles(), + mbfe, + jpaql, + parameters); + } catch (HibernateException he) { + throw new TopiaQueryException( + "unable to stream", + he, + jpaql, + parameters); + } catch (RuntimeException re) { + throw new TopiaQueryException( + "unable to stream", + re, + jpaql, + parameters); + } + } + @Override public <T> T findAny(String jpaql, Map<String, Object> 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 e7de7314..bc49bb91 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 @@ -28,6 +28,7 @@ import org.nuiton.topia.persistence.QueryMissingOrderException; import java.util.List; import java.util.Map; +import java.util.stream.Stream; /** * This API provides methods to use persistence using JPA queries @@ -51,6 +52,18 @@ public interface TopiaJpaSupport { <T> List<T> findAll(String jpaql, Map<String, Object> parameters); /** + * Streaming on the result of a {@link #findAll}. + * + * Streaming is not part of JPA but may be part a JPA implementation so we provide + * a default implementation that will work on any JPA vendor. + * + * @since 3.4 + */ + default <T> Stream<T> stream(String jpaql, Map<String, Object> parameters) { + return this.<T>findAll(jpaql, parameters).stream(); + } + + /** * Allow to do some JPA-QL query using the given bounds. * <ul> * <li>No lower bound : {@code startIndex = 0}.</li> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
participants (1)
-
nuiton.org scm