Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/LazyCollectionUtils.java')
-rw-r--r--hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/LazyCollectionUtils.java307
1 files changed, 307 insertions, 0 deletions
diff --git a/hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/LazyCollectionUtils.java b/hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/LazyCollectionUtils.java
new file mode 100644
index 000000000..ba3f3fbb1
--- /dev/null
+++ b/hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/LazyCollectionUtils.java
@@ -0,0 +1,307 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2005, 2006, 2007, 2008 Springsite BV (The Netherlands) and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Martin Taal
+ * </copyright>
+ *
+ * $Id: LazyCollectionUtils.java,v 1.9 2010/08/18 11:50:38 mtaal Exp $
+ */
+
+package org.eclipse.emf.teneo.hibernate;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.eclipse.emf.teneo.hibernate.mapping.eav.EAVDelegatingList;
+import org.eclipse.emf.teneo.hibernate.mapping.eav.EAVValueHolder;
+import org.eclipse.emf.teneo.mapping.elist.PersistableDelegateList;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.collection.AbstractPersistentCollection;
+import org.hibernate.engine.CollectionEntry;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.hql.ast.util.SessionFactoryHelper;
+import org.hibernate.persister.collection.AbstractCollectionPersister;
+import org.hibernate.persister.collection.QueryableCollection;
+
+/**
+ * A utility class providing methods related to lazy loading of collections.
+ *
+ * @author <a href="mailto:mtaal@elver.org">Martin Taal</a>
+ * @version $Revision: 1.9 $
+ */
+public class LazyCollectionUtils {
+
+ public final static int DEFAULT_PAGE_SIZE = 100;
+
+ /**
+ * Returns an iterator which loads the underlying data from the collection
+ * in pages (controlled by the pageSize parameter). Note if the collection
+ * is not lazy loadable then a normal iterator is returned. This is checked
+ * using the {@link #isLazyLoadableCollection(Collection)} method.
+ *
+ * Note: this method can only handle collections of EObjects so not collections
+ * of primitive typed objects. Paged iteration of these collections is not
+ * supported by Hibernate.
+ *
+ * @param coll
+ * the collection to iterate lazily over
+ * @param pageSize
+ * the pageSize, this determines the pagesize of the page of data
+ * read each time from the database
+ * @return a paging iterator or if not a lazy loadable collection a normal
+ * iterator
+ * @see PagingIterator
+ */
+ public static <E> Iterator<E> getPagedLoadingIterator(Collection<E> coll,
+ int pageSize) {
+ if (!isLazyLoadableCollection(coll)) {
+ return coll.iterator();
+ }
+ final PersistableDelegateList<?> persistableList = (PersistableDelegateList<?>) coll;
+ final AbstractPersistentCollection persistentCollection = (AbstractPersistentCollection) persistableList
+ .getDelegate();
+
+ final SessionImplementor session = persistentCollection.getSession();
+ final PagingIterator<E> pagingIterator = new PagingIterator<E>();
+ pagingIterator.setCollection(persistentCollection);
+ pagingIterator.setPageSize(pageSize);
+ pagingIterator.setSession((Session) session);
+
+ final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry(persistentCollection);
+ final AbstractCollectionPersister persister = (AbstractCollectionPersister)entry.getLoadedPersister();
+ pagingIterator.setEavCollection(coll instanceof EAVDelegatingList);
+ pagingIterator.setIndexColumnNames(persister.getIndexColumnNames());
+ return pagingIterator;
+ }
+
+ /**
+ * Reads the size of a collection in a lazy manner, i.e. will try to not
+ * load the collection from the database. The size is cached in the object,
+ * so subsequent calls to this method will not result in additional database
+ * queries. This until the collection changes then the cache is cleared.
+ *
+ * Note if the collection can not be lazy loaded (see the
+ * {@link #isLazyLoadableCollection(Collection)}) then the size method is
+ * called on the collection. This method call is probably not lazy.
+ *
+ * @param coll
+ * the collection to get the size from
+ * @return the size of the collection
+ */
+ public static int size(Collection<?> coll) {
+ if (!isLazyLoadableCollection(coll)) {
+ return coll.size();
+ }
+ final PersistableDelegateList<?> persistableList = (PersistableDelegateList<?>) coll;
+ final AbstractPersistentCollection persistentCollection = (AbstractPersistentCollection) persistableList
+ .getDelegate();
+ final SessionImplementor session = persistentCollection.getSession();
+ final QueryableCollection persister = new SessionFactoryHelper(session
+ .getFactory()).getCollectionPersister(persistentCollection
+ .getRole());
+ return persister.getSize(persistentCollection.getKey(), session);
+ }
+
+ /**
+ * Determines if a collection can be lazy loaded. A lazy loadable collection
+ * must be a {@link PersistableDelegateList} which has a
+ * {@link AbstractPersistentCollection} as the delegate list which also must
+ * have an open Hibernate session.
+ *
+ * @param coll
+ * the collection for which to determine if it can be lazy loaded
+ * @return false if not lazy loadable, true otherwise
+ */
+ public static <E> boolean isLazyLoadableCollection(Collection<E> coll) {
+ boolean lazyLoadable = coll instanceof PersistableDelegateList<?>;
+ if (!lazyLoadable) {
+ return false;
+ }
+ final PersistableDelegateList<?> persistableList = (PersistableDelegateList<?>) coll;
+ lazyLoadable &= persistableList.getDelegate() instanceof AbstractPersistentCollection;
+ if (!lazyLoadable) {
+ return false;
+ }
+ final AbstractPersistentCollection persistentCollection = (AbstractPersistentCollection) persistableList
+ .getDelegate();
+ final SessionImplementor session = persistentCollection.getSession();
+ // if not a valid session then go away
+ if (session == null
+ || !session.isOpen()
+ || !session.getPersistenceContext().containsCollection(
+ persistentCollection)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * A paging iterator reads the underlying data from the database in pages.
+ * Everytime the iterator reaches the end of a page it reads the next page
+ * from the database.
+ *
+ * @author mtaal
+ */
+ public static class PagingIterator<E> implements Iterator<E> {
+
+ private Session session;
+ private int pageSize;
+ private Boolean hasNext = null;
+ private int currentIteratorIndex = 0;
+ private int nextPageStart = 0;
+ private List<E> content;
+ private Object collection;
+ private String[] indexColumnNames;
+ private String orderBy = "";
+ private boolean eavCollection;
+
+ public boolean hasNext() {
+ if (content == null) {
+ setPageInformation();
+ }
+
+ if (currentIteratorIndex < content.size()) {
+ return true;
+ }
+
+ if (hasNext != null) {
+ return hasNext;
+ }
+
+ if (content.size() < pageSize) {
+ hasNext = false;
+ return hasNext;
+ }
+
+ // load the next page to see if there is any content
+ hasNext = !loadNextPage().isEmpty();
+
+ return hasNext;
+ }
+
+ public E next() {
+ if (currentIteratorIndex < content.size()) {
+ return convert(content.get(currentIteratorIndex++));
+ }
+
+ // load the next page
+ setPageInformation();
+ if (content.isEmpty()) {
+ throw new NoSuchElementException();
+ }
+ return convert(content.get(currentIteratorIndex++));
+ }
+
+ @SuppressWarnings("unchecked")
+ private E convert(E value) {
+ if (value instanceof EAVValueHolder) {
+ return (E) ((EAVValueHolder) value).getValue();
+ }
+ return value;
+ }
+
+ private void setPageInformation() {
+ content = loadNextPage();
+ currentIteratorIndex = 0;
+ hasNext = null;
+ nextPageStart += content.size();
+ }
+
+ @SuppressWarnings("unchecked")
+ private List<E> loadNextPage() {
+ final Query query;
+ if (isEavCollection()) {
+ query = session.createFilter(collection,
+ " order by this.listIndex ");
+ } else {
+ query = session.createFilter(collection, orderBy);
+ }
+ query.setMaxResults(pageSize);
+ query.setFirstResult(nextPageStart);
+ return (List<E>) query.list();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException(
+ "Removal is not supported by the paging iterator");
+ }
+
+ public Session getSession() {
+ return session;
+ }
+
+ public void setSession(Session session) {
+ this.session = session;
+ }
+
+ public int getPageSize() {
+ return pageSize;
+ }
+
+ public void setPageSize(int pageSize) {
+ this.pageSize = pageSize;
+ }
+
+ public Object getCollection() {
+ return collection;
+ }
+
+ public void setCollection(Object collection) {
+ this.collection = collection;
+ }
+
+ public String[] getIndexColumnNames() {
+ return indexColumnNames;
+ }
+
+ public void setIndexColumnNames(String[] indexColumnNames) {
+ this.indexColumnNames = indexColumnNames;
+ final StringBuilder sb = new StringBuilder();
+ if (indexColumnNames != null) {
+ for (String indexColumnName : indexColumnNames) {
+ if (sb.length() == 0) {
+ sb.append(" order by ");
+ } else {
+ sb.append(", ");
+ }
+ sb.append(indexColumnName.replaceAll("`", "").replaceAll(
+ "\"", ""));
+ }
+ }
+ orderBy = sb.toString();
+ }
+
+ public String getOrderBy() {
+ return orderBy;
+ }
+
+ /**
+ * Note the parameter must include the term: order by. Refer to properties of
+ * the collection content using the this keyword.
+ *
+ * @param orderBy the order by clause including the order by keyword, for example: order by this.name
+ */
+ public void setOrderBy(String orderBy) {
+ this.orderBy = orderBy;
+ }
+
+ public boolean isEavCollection() {
+ return eavCollection;
+ }
+
+ public void setEavCollection(boolean eavCollection) {
+ this.eavCollection = eavCollection;
+ }
+
+ }
+} \ No newline at end of file

Back to the top