only one character more to type FooRecord.getKey(someId) than to type
FooRecord.class, someId and with the new Key.newKey() methods, you can also
create ad hoc keys briefly when needed.
initialization to not hit the database at all in the up-to-date case (after a
single query to load the versions of all known records). This is about six
hundred fewer queries than we were doing on Whirled at server startup. To be
fair, they were pretty fast queries. :)
*) We do not currently invalidate cached keysets even when we know for a fact that the associated records have changed (and exactly how they've changed). By storing along with each cached keyset the query datastructure that was used to fetch the keys, we can use the SQLExpression evaluator to do a secondary invalidation sweep over the records when they're requested and make sure they still match the WHERE clause of the original query. If they don't, we toss'em from the cached keyset. This basically means we can trust our cached keysets much more and increase the amount of time we keep them around in the cache.
*) Extending the first idea, we can do more than lazily invalidate parts of cached collections. We can, in fact, automatically adjust every relevant cached collection each time a record is deleted, inserted or modified. In theory, we could guarantee perpetual veracity of all cached collection queries. It's not a given that this is in every way a good idea, but it's a very interesting one to investigate.
As part of this change, ExpressionVisitor methods have to return a value. Slightly less elegant, but of greater general utility.
dangerous. The "key" (which identifies the rows you want to change) was
[ColumnExp, Comparable, ...] and the data that you would be changing was
[ColumnExp, Object]. So if you happened to pass a comparable object as the
first value you wanted to change, say:
updatePartial(FooRecord.class, FooRecord.FOO_ID, 5, FooRecord.BAR_ID, 6,
FooRecord.BAZ, "biffle")
the compiler would think you wanted to use FOO_ID and BAR_ID as a key rather
than FOO_ID as a key and BAR_ID as something to be updated. Either way, it's
not clear what you want, so it should go. Now you have to create a Key():
updatePartial(new Key<FooRecord>(FooRecord.clsas, FooRecord.FOO_ID, 5,
FooRecord.BAR_ID, 6),
FooRecord.BAZ, "biffle")
or
updatePartial(new Key<FooRecord>(FooRecord.clsas, FooRecord.FOO_ID, 5),
FooRecord.BAR_ID, 6, FooRecord.BAZ, "biffle")
None of our code was doing this anyway. We were already using Key everywhere or
the (Class, Comparable) method for records with a single column as primary key.