com.j256.ormlite.dao.LazyForeignCollection Maven / Gradle / Ivy
package com.j256.ormlite.dao;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.field.ForeignCollectionField;
import com.j256.ormlite.misc.IOUtils;
import com.j256.ormlite.support.DatabaseConnection;
/**
* Collection that is set on a field that as been marked with the {@link ForeignCollectionField} annotation when an
* object is refreshed or queried (i.e. not created). Most of the methods here require a pass through the database.
* Operations such as size() therefore should most likely not be used because of their expense. Chances are you only
* want to use the {@link #iterator()}, {@link #toArray()}, and {@link #toArray(Object[])} methods.
*
*
* WARNING: Most likely for(;;) loops should not be used here since we need to be careful about closing the
* iterator.
*
*
* @author graywatson
*/
public class LazyForeignCollection extends BaseForeignCollection implements Serializable {
private static final long serialVersionUID = -5460708106909626233L;
private transient CloseableIterator lastIterator;
/**
* WARNING: The user should not be calling this constructor. You should be using the
* {@link Dao#assignEmptyForeignCollection(Object, String)} or {@link Dao#getEmptyForeignCollection(String)} methods
* instead.
*/
public LazyForeignCollection(Dao dao, Object parent, Object parentId, FieldType foreignFieldType,
String orderColumn, boolean orderAscending) {
super(dao, parent, parentId, foreignFieldType, orderColumn, orderAscending);
}
/**
* The iterator returned from a lazy collection keeps a connection open to the database as it iterates across the
* collection. You will need to call {@link CloseableIterator#close()} or go all the way through the loop to ensure
* that the connection has been closed. You can also call {@link #closeLastIterator()} on the collection itself
* which will close the last iterator returned. See the reentrant warning.
*/
@Override
public CloseableIterator iterator() {
return closeableIterator(DatabaseConnection.DEFAULT_RESULT_FLAGS);
}
@Override
public CloseableIterator iterator(int flags) {
return closeableIterator(flags);
}
@Override
public CloseableIterator closeableIterator() {
return closeableIterator(DatabaseConnection.DEFAULT_RESULT_FLAGS);
}
@Override
public CloseableIterator closeableIterator(int flags) {
try {
return iteratorThrow(flags);
} catch (SQLException e) {
throw new IllegalStateException("Could not build lazy iterator for " + dao.getDataClass(), e);
}
}
@Override
public CloseableIterator iteratorThrow() throws SQLException {
return iteratorThrow(DatabaseConnection.DEFAULT_RESULT_FLAGS);
}
@Override
public CloseableIterator iteratorThrow(int flags) throws SQLException {
CloseableIterator li = seperateIteratorThrow(flags);
lastIterator = li;
// make sure we return the local variable instead of the field for concurrency reasons
return li;
}
@Override
public CloseableWrappedIterable getWrappedIterable() {
return getWrappedIterable(DatabaseConnection.DEFAULT_RESULT_FLAGS);
}
@Override
public CloseableWrappedIterable getWrappedIterable(final int flags) {
return new CloseableWrappedIterableImpl(new CloseableIterable() {
@Override
public CloseableIterator iterator() {
return closeableIterator();
}
@Override
public CloseableIterator closeableIterator() {
try {
return LazyForeignCollection.this.seperateIteratorThrow(flags);
} catch (Exception e) {
throw new IllegalStateException("Could not build lazy iterator for " + dao.getDataClass(), e);
}
}
});
}
@Override
public void closeLastIterator() throws Exception {
if (lastIterator != null) {
lastIterator.close();
lastIterator = null;
}
}
@Override
public boolean isEager() {
return false;
}
@Override
public int size() {
CloseableIterator iterator = iterator();
try {
int sizeC;
for (sizeC = 0; iterator.hasNext(); sizeC++) {
// move to next without constructing the object
iterator.moveToNext();
}
return sizeC;
} finally {
IOUtils.closeQuietly(iterator);
}
}
@Override
public boolean isEmpty() {
CloseableIterator iterator = iterator();
try {
return !iterator.hasNext();
} finally {
IOUtils.closeQuietly(iterator);
}
}
@Override
public boolean contains(Object obj) {
CloseableIterator iterator = iterator();
try {
while (iterator.hasNext()) {
if (iterator.next().equals(obj)) {
return true;
}
}
return false;
} finally {
IOUtils.closeQuietly(iterator);
}
}
@Override
public boolean containsAll(Collection collection) {
Set