Like other ORM frameworks, a query in Cayenne reads the database. But unlike other ORM frameworks, Cayenne only writes changes to the database upon a commit. This means that a query will not see changes made in the same transaction:
ObjectContext ctx = runtime.newContext();
// Searches for an item with id 1.
Item item = Cayenne.objectForPK(ctx, Item.class, 1);
System.out.println("" + item.getValue()); // output is 42.
// Changes the value but doesn't commit.
item.setValue(84);
// Searches (in the database) with new attribute value. Item is not found.
Item copy1 = ObjectSelect.query(Item.class).where(Item.VALUE.eq(84)).selectOne(ctx);
if (copy1 == null) System.out.println("not found"); // output: "not found".
// Searches (in the database) with old attribute value. Item is found.
Item copy2 = ObjectSelect.query(Item.class).where(Item.VALUE.eq(42)).selectOne(ctx);
// But item has the new attribute values cached in the ObjectContext.
System.out.println("" + copy2.getValue()); // output is 84.
A possible but cumbersome solution would be to always query the database and the ObjectContext:
Item copy = ObjectSelect.query(Item.class).where(Item.VALUE.eq(84)).selectOne(ctx);
if (copy == null) copy = (Item) Item.VALUE.eq(84).first(new ArrayList<>(ctx.uncommittedObjects()));
System.out.println("" + copy.getValue()); // output: "84".
What is the best practice to find an object within the same transaction that may have been modified or newly created?