Skip to content

Commit

Permalink
Added additional methods to support the flags param in all iterator
Browse files Browse the repository at this point in the history
modes.  Thanks to Igromanru.
  • Loading branch information
Gray Watson committed Aug 5, 2013
1 parent c5d358e commit d4fde06
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 26 deletions.
3 changes: 1 addition & 2 deletions src/main/java/com/j256/ormlite/dao/Dao.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
Expand Down Expand Up @@ -341,7 +340,7 @@ public interface Dao<T, ID> extends CloseableIterable<T> {

/**
* Same as {@link #iterator()} but while specifying flags for the results. This is necessary with certain database
* types. The resultFlags could be something like {@link ResultSet#TYPE_SCROLL_INSENSITIVE} or other values.
* types. The resultFlags could be something like ResultSet.TYPE_SCROLL_INSENSITIVE or other values.
*
* <p>
* <b>WARNING:</b> Depending on the database type the underlying connection may never be freed -- even if you go all
Expand Down
21 changes: 19 additions & 2 deletions src/main/java/com/j256/ormlite/dao/EagerForeignCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.field.ForeignCollectionField;
import com.j256.ormlite.support.DatabaseConnection;
import com.j256.ormlite.support.DatabaseResults;

/**
Expand Down Expand Up @@ -39,14 +40,26 @@ public EagerForeignCollection(Dao<T, ID> dao, Object parent, Object parentId, Fi
}

public CloseableIterator<T> iterator() {
return iteratorThrow();
return iteratorThrow(DatabaseConnection.DEFAULT_RESULT_FLAGS);
}

public CloseableIterator<T> iterator(int flags) {
return iteratorThrow(flags);
}

public CloseableIterator<T> closeableIterator() {
return iteratorThrow();
return iteratorThrow(DatabaseConnection.DEFAULT_RESULT_FLAGS);
}

public CloseableIterator<T> closeableIterator(int flags) {
return iteratorThrow(DatabaseConnection.DEFAULT_RESULT_FLAGS);
}

public CloseableIterator<T> iteratorThrow() {
return iteratorThrow(DatabaseConnection.DEFAULT_RESULT_FLAGS);
}

public CloseableIterator<T> iteratorThrow(int flags) {
// we have to wrap the iterator since we are returning the List's iterator
return new CloseableIterator<T>() {
private int offset = -1;
Expand Down Expand Up @@ -139,6 +152,10 @@ public CloseableWrappedIterable<T> getWrappedIterable() {
return this;
}

public CloseableWrappedIterable<T> getWrappedIterable(int flags) {
return this;
}

public void close() {
// noop since the iterators aren't holding open a connection
}
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/com/j256/ormlite/dao/ForeignCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,41 @@
*/
public interface ForeignCollection<T> extends Collection<T>, CloseableIterable<T> {

/**
* Like {@link Collection#iterator()} but while specifying flags for the results. This is necessary with certain
* database types. The resultFlags could be something like ResultSet.TYPE_SCROLL_INSENSITIVE or other
* values.
*/
public CloseableIterator<T> iterator(int flags);

/**
* Same as {@link #iterator(int)}.
*/
public CloseableIterator<T> closeableIterator(int flags);

/**
* Like {@link Collection#iterator()} but returns a closeable iterator instead and can throw a SQLException.
*/
public CloseableIterator<T> iteratorThrow() throws SQLException;

/**
* Like {@link #iteratorThrow()} but while specifying flags for the results. This is necessary with certain database
* types. The resultFlags could be something like ResultSet.TYPE_SCROLL_INSENSITIVE or other values.
*/
public CloseableIterator<T> iteratorThrow(int flags) throws SQLException;

/**
* This makes a one time use iterable class that can be closed afterwards. The ForeignCollection itself is
* {@link CloseableWrappedIterable} but multiple threads can each call this to get their own closeable iterable.
*/
public CloseableWrappedIterable<T> getWrappedIterable();

/**
* Like {@link #getWrappedIterable()} but while specifying flags for the results. This is necessary with certain
* database types. The resultFlags could be something like ResultSet.TYPE_SCROLL_INSENSITIVE or other values.
*/
public CloseableWrappedIterable<T> getWrappedIterable(int flags);

/**
* This will close the last iterator returned by the {@link #iterator()} method.
*
Expand Down
50 changes: 30 additions & 20 deletions src/main/java/com/j256/ormlite/dao/LazyForeignCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.field.ForeignCollectionField;
import com.j256.ormlite.support.DatabaseConnection;

/**
* Collection that is set on a field that as been marked with the {@link ForeignCollectionField} annotation when an
Expand Down Expand Up @@ -43,47 +44,46 @@ public LazyForeignCollection(Dao<T, ID> dao, Object parent, Object parentId, Fie
* which will close the last iterator returned. See the reentrant warning.
*/
public CloseableIterator<T> iterator() {
return closeableIterator();
return closeableIterator(DatabaseConnection.DEFAULT_RESULT_FLAGS);
}

public CloseableIterator<T> iterator(int flags) {
return closeableIterator(flags);
}

public CloseableIterator<T> closeableIterator() {
return closeableIterator(DatabaseConnection.DEFAULT_RESULT_FLAGS);
}

public CloseableIterator<T> closeableIterator(int flags) {
try {
return iteratorThrow();
return iteratorThrow(flags);
} catch (SQLException e) {
throw new IllegalStateException("Could not build lazy iterator for " + dao.getDataClass(), e);
}
}

/**
* This is the same as {@link #iterator()} except it throws.
*/
public CloseableIterator<T> iteratorThrow() throws SQLException {
lastIterator = seperateIteratorThrow();
return lastIterator;
return iteratorThrow(DatabaseConnection.DEFAULT_RESULT_FLAGS);
}

/**
* Same as {@link #iteratorThrow()} except this doesn't set the last iterator which can be closed with the
* {@link #closeLastIterator()}.
*/
public CloseableIterator<T> seperateIteratorThrow() throws SQLException {
// check state to make sure we have a DAO in case we have a deserialized collection
if (dao == null) {
throw new IllegalStateException(
"Internal DAO object is null. Lazy collections cannot be used if they have been deserialized.");
} else {
return dao.iterator(getPreparedQuery());
}
public CloseableIterator<T> iteratorThrow(int flags) throws SQLException {
lastIterator = seperateIteratorThrow(flags);
return lastIterator;
}

public CloseableWrappedIterable<T> getWrappedIterable() {
return getWrappedIterable(DatabaseConnection.DEFAULT_RESULT_FLAGS);
}

public CloseableWrappedIterable<T> getWrappedIterable(final int flags) {
return new CloseableWrappedIterableImpl<T>(new CloseableIterable<T>() {
public CloseableIterator<T> iterator() {
return closeableIterator();
}
public CloseableIterator<T> closeableIterator() {
try {
return LazyForeignCollection.this.seperateIteratorThrow();
return LazyForeignCollection.this.seperateIteratorThrow(flags);
} catch (Exception e) {
throw new IllegalStateException("Could not build lazy iterator for " + dao.getDataClass(), e);
}
Expand Down Expand Up @@ -303,4 +303,14 @@ public boolean equals(Object other) {
public int hashCode() {
return super.hashCode();
}

private CloseableIterator<T> seperateIteratorThrow(int flags) throws SQLException {
// check state to make sure we have a DAO in case we have a deserialized collection
if (dao == null) {
throw new IllegalStateException(
"Internal DAO object is null. Lazy collections cannot be used if they have been deserialized.");
} else {
return dao.iterator(getPreparedQuery(), flags);
}
}
}
67 changes: 65 additions & 2 deletions src/test/java/com/j256/ormlite/dao/ForeignCollectionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -779,6 +780,28 @@ public void testEagerCollectionIterator() throws Exception {
assertNull(iterator.moveRelative(1));
assertNull(iterator.previous());
assertEquals(order1, iterator.first());
iterator.closeQuietly();
}

@Test
public void testEagerCollectionIteratorRemove() throws Exception {
Dao<Account, Integer> accountDao = createDao(Account.class, true);
Dao<Order, Integer> orderDao = createDao(Order.class, true);

Account account = new Account();
account.name = "fwejpojfpofewjo";
assertEquals(1, accountDao.create(account));

Order order1 = new Order();
order1.account = account;
order1.val = 1;
assertEquals(1, orderDao.create(order1));
Order order2 = new Order();
order2.account = account;
order2.val = 2;
assertEquals(1, orderDao.create(order2));

Account result = accountDao.queryForId(account.id);

// test remove of the certain element and iterator's behavior after that
Order order3 = new Order();
Expand All @@ -787,12 +810,52 @@ public void testEagerCollectionIterator() throws Exception {
assertEquals(1, orderDao.create(order3));
accountDao.refresh(result);

iterator = result.orders.iteratorThrow();
CloseableIterator<Order> iterator = result.orders.iteratorThrow();
assertEquals(order1, iterator.next());
assertEquals(order2, iterator.next());
iterator.remove();
assertEquals(order3, iterator.next());
assertEquals(order1, iterator.previous());
iterator.closeQuietly();
}

@Test
public void testLazyCollectionIteratorRemove() throws Exception {
Dao<LazyNode, Integer> nodeDao = createDao(LazyNode.class, true);
Dao<LazyConnection, Integer> connDao = createDao(LazyConnection.class, true);

LazyNode node = new LazyNode();
node.stuff = "fwejpojfpofewjo";
assertEquals(1, nodeDao.create(node));

LazyConnection conn1 = new LazyConnection();
conn1.to = node;
conn1.stuff = "1231331";
assertEquals(1, connDao.create(conn1));
LazyConnection conn2 = new LazyConnection();
conn2.to = node;
conn2.stuff = "fwgregreegr";
assertEquals(1, connDao.create(conn2));
LazyConnection conn3 = new LazyConnection();
conn3.to = node;
conn3.stuff = "beehergregr";
assertEquals(1, connDao.create(conn3));

LazyNode result = nodeDao.queryForId(node.id);
CloseableIterator<LazyConnection> iterator = result.tos.iteratorThrow(ResultSet.TYPE_SCROLL_INSENSITIVE);
assertTrue(iterator.hasNext());
assertEquals(conn1, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(conn2, iterator.next());
iterator.remove();
assertTrue(iterator.hasNext());
assertEquals(conn3, iterator.next());
/*
* NOTE: this is conn2 in the lazy test because the cursor sees the data that has been removed underneath the
* covers. Not sure how to fix this.
*/
assertEquals(conn2, iterator.previous());
iterator.closeQuietly();
}

@Test
Expand Down Expand Up @@ -1725,7 +1788,7 @@ protected static class ForeignAutoRefreshSame {
int id;
@DatabaseField
String stuff;
@DatabaseField(foreign = true/*, foreignAutoRefresh = true*/)
@DatabaseField(foreign = true/* , foreignAutoRefresh = true */)
ForeignAutoRefreshSameCollection foreign;
public ForeignAutoRefreshSame() {
}
Expand Down

0 comments on commit d4fde06

Please sign in to comment.