Trouble caching collections with Hibernate and EhCache
as the topic suggests, I'm having some trouble with Hibernate and EhCache.
I'm using Hibernate with mySql and EhCache in a Resteasy-application.
The model: There are a few entities, some are one-to-many and some one-to-one relations.
- Measuring
- headerinformation (one-to-one)
- content (one-to-one)
- places (one-to-one (I need this element because of its metadata)
- place (collection with place-entities) (one-to-many lazy)
- measure (collection with measure-entities) (one-to-many lazy)
- timedcode (collection with timecode-eintities (one-to-many lazy)
- measure (collection with measure-entities) (one-to-many lazy)
- place (collection with place-entities) (one-to-many lazy)
- places (one-to-one (I need this element because of its metadata)
The problem: I'm trying to get all my data in a query like createQuery("from Measuring c").list()
. Now there a two ways to cache the result: Querycache and 2nd-level-cache.
The querycache will only cache the select for the measuring-entity, needless to say that this is not thebehaviour I expected. Well I want the querycache to cache all the sql-statements. Is there any way to get this to work?
I have activated the cache for all entities. The 2nd-level-cache will cache the elements but won't hit them again (well it does, but only measuring-element); some little thoughts later I realized that I have to cache the collections to let the cache know which elements belong together.
Well, activating the caches for all one-to-many collections works great in case of fetching all data as first cache request. But if there wouldn't be a problem i wouldn't write this. Querying a place by one of its fields as first cache-action will cause the cache to do what it should: it caches the requested data, that means a measuring-entity (actually there is only one in the database), a headerinformation, content with places-element and the found place with its sub-elements. Querying another place also works great. Now I want to get all the ele开发者_Go百科ments (the query mentioned above), but I only get the already queried ones. It seems that hibernate queries only the cache if the statement contains no selection-criteria. This seems to be a little problem when caching collections.
So what I need is either getting the query cache to cache all statements or the 2nd-level-cache retrieving the entire collection if it's requested but already a concrete one was executed.
I also have to mention that when retrieving a concrete place (or all elements) i need to get the complete measuring element (with its headerinformation etc.), because the rest-service answers in xml and the applications on the other side need to get an measuring element with all its possible nodes.
Well I could imagine, that there are some mistakes in my queries. So here are both mentioned queries:
Get all the data: createQuery("from Measuring c").setCacheable(true).list()
Get data with a concrete place: createQuery("from Measuring measuringElement join fetch measuringElement.content contentElement join fetch contentElement.places placesElement join fetch placesElement.places placeElement WHERE placeElement.name = '" + name +"'").setCacheable(true).list()
.
Can anybody help me?
Many many thanks in advance and kind regards
Your question is very hard to understand, so I'll just explain how the caches work.
You may cache three things:
- entities
- collections of entities (i.e. ToMany associations)
- queries
The cache of entities will be hit when using get or load, and when navigating from another entity to the cached entity through a ToOne association. Only the fields of the entity are cached. Not the ToMany associations.
The cache of collections will be hit when navigating through a cached ToMany association. The cache only stores the ID of the entities in the collection. Hibernate will try to get all the entities of the collection one by one using the cached IDs. To be efficient, the target entities should thus also be in the entity cache.
The query cache will be hit when executing a cached query. When the query returns entity instances (such as the two queries of your question), the query cache only stores the IDs of the root entities returned by the query. It doesn't cache the whole result. Hibernate will try to get all the entities of the collection one by one using the cached IDs. To be efficient, the target entities should thus also be in the entity cache.
So, if you want to execute a query returning an entity with all its associations recursively, you should make the query cacheable, make the ToMany associations cacheable, and make each entity of the graph cacheable.
I had to do
<set lazy="false" ...>
or iterate over the collection, otherwise the collection is not written in Ehcache.
精彩评论