> What sort of scenarios might lead
> Ebean to pull from the cache in such a way that the cache does not
> represent what's in the database?
The Persistence Context (L1 Cache) is transaction scoped... so as long
as the query used a different transaction it could not use the
original L1 cache. Technically the Persistence Context does live
beyond the end of a transaction as it is used for lazy loading - but
it is not used for any 'new queries'.
Advanced Note: We could actually make the Persistence Context longer
lived than transaction scoped ("JPA Extended Persistence Context") but
there was been no need to date and I don't forsee it. (JPA on the
other hand does need this).
> Even if not, with the L2 cache on
Yes. The L2 cache is not strictly 'read consistent' with the DB. That
is, the L2 cache is updated after the successful DB commit so there is
a small time lag between those 2 events where a different thread can
hit the cache and got a 'stale' bean from the cache.
With the Lucene Integration coming ... you can think of the L2 cache
being backed by Lucene - and at this stage I have made this
non-transactional (like SOLR and unlike Compass).
The net net... is that if you need to guarantee read consistency we
should be hitting the DB and NOT using the L2 cache (L2 bean cache or
Lucene indexes). Alternatively we could use a 'transactional cache'
with the extra costs of 2PC etc but personally I'd rather lean on the
DB for read consistency and live with the non-strict L2 cache.
That said, there are a lot of cases where we don't need strict read
consistency and want to use the L2 bean cache or Lucene indexes for
the benefits of performance and horizontal scalability.
This is a big subject ... hopefully that made some sense.
Cheers, Rob.
Correct.
> Out of curiosity (it will be a long time before I'm using Ebean with
> L2 cache), do you run the root SQL query against the database to get
> primary keys, then either pull a bean from the L2 cache, if present,
> or populate from result sets?
The L2 cache is a bunch of bean caches (1 Map per type with the Id as
the key) ... and a bunch of query caches (1 Map per type with the
query hash as the key).
The bean cache currently is used for find by Id, getReference and
joins. In the "joins" case we the final object graphs are a mix of
data from the resultset and the L2 cache.
> But the children of A (B's) are stale.
If we hit the cache with read-only=false then the beans returned from
the L2 cache are flat so their children will be loaded on demand. If
you hit the cache with read-only-true then Ebean can give you shared
instances and the cached bean could have children loaded (that are all
marked as 'shared instances' and immutable).
With Lucene it will be a bit different in that we can effectively have
the local Lucene index act like a DB materialised view for many
queries (depending on the query and the expressions used) and we can
either use the "bean cache" or not.
I don't think this fully answers your question though...
On 6/19/10, Daryl Stultz <kungfum...@gmail.com> wrote:
>
>
Yes.
> Does that apply to single associations as well?
Yes. Both *ToOne and *ToMany are loaded on demand.