What is the correct why to get EclipseLink JPA query.getResultList() results in the cache? - jpa

When I use EclipseLink JPA query.getResultList() it doesn't store the results in the cache so when I call merge the first call does a select all then update for each object.
What's the correct all to get query results in the cache?
I'm thinking do the query then call EntityManager find for each result - but seems wrong. Obviously I can't call find first as I don't know the object id.
Basically I want to cache all the data in-memory (in the cache) and have updates as quick as possible.
Thanks

EclipseLink caches every object returned by getResultList() in the shared (L2) cache by default.
If you are not getting caching, then you have mis-configured something.
Please include your code, configuration, and SQL log.
Are you using Spring? (see http://www.eclipse.org/forums/index.php/t/200321/)
Ensure you have not disabled the shared cache, or configured refreshing.
How many object are you reading, and how long is it from the query to the merge? If you are reading a lot of objects, you may need to increase the cache size (default is 100), or change the cache type.
See, http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching

Related

JPA First level cache and when its filled

working with Spring data JPA and reading it Hibernate first level cache is missed, the answer says "Hibernate does not cache queries and query results by default. The only thing the first level cache is used is when you call EntityManger.find() you will not see a SQL query executing. And the cache is used to avoid object creation if the entity is already loading."
So, if If get an entity not by its Id but other criteria, if I update some property I should not see an update sql inside a transactional methods because it has not been stored int the first level cache, right?
According to the above answer, if I get some list of entities, they will not be stored in first level cache not matter the criteria I use to find them, right?
When a Transactional(propagation= Propagation.NEVER) method loads the same entity by its id two times, is not supposed it will hit the database two times because each loading will run in its own "transaction" and will have its own persistent context? What is the expected behaviour in this case?
Thanks

Eclipselink disable cache for stored procedure

I have two stored procedure calls that return a User entity. One looks to see if the user is registered by two parameters not included in the user entity. If the procedure does not return any users, a second stored procedure is called to register that user.
The behavior I'm seeing is that when called in this order, the second stored procedure returns a User entity from the cache that has nearly all the fields as null. When I disable caching it returns the user object appropriately. It would seem that the first call is caching the user object.
In normal operation where a user is logging in, I want it to cache, so I do not want to disable caching for the first call. I want the second stored procedure call to not use the cache. After doing some research and testing a few options, I've found few options.
This doesn't work on a stored procedure:
proc.setHint("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
java.lang.IllegalArgumentException: Query linkUser, query hint javax.persistence.cache.retrieveMode is not valid for this type of query.
This looks like evicts all the cache for all Users.
em.getEntityManagerFactory().getCache().evict(User.class);
And these options either disable cache for all instances of the entity or across the application.
How can I not use cache for a single stored procedure call with Eclipselink?
Bonus: Why would a stored procedure call that returns a null user be cached?
The JPA specification requires that all entities returned from JPA queries (which includes native and Stored proc queries) be managed, which implies they are also cached to maintain object identity. If your first query is returning an incomplete entity, this too will be cached. Applications need to be careful when using queries that return entities that they return a complete set of data or they can corrupt the cache, and also note that their entities may be pulled from the cache instead of rebuilt with the data from their query, and may want to return java objects (constructor queries) rather than JPA entities.
For the answer to the first part, see https://stackoverflow.com/a/4471109/496099
Found a Java EE Tutorial that shows how evict an individual cache. I'm still not sure why it's even being cached because the first call never has the userId.
Cache cache = em.getEntityManagerFactory().getCache();
cache.evict(User.class, userId);

Data retrieval fails after clearing Local

I'm writing unit tests for entity framework, using the Effort in memory db.
In one set of tests the EF part creates an object and adds some existing objects to a child list in it (think Master / Detail). Then it SavesChanges
In the unit test I then retrieve the record from EF and check that it actually got there and the children are in place: they are.
However, I want to be sure that I'm not just reading the data from the cache and that it actually got persisted. So I Clear() the Local cache in the DbSet.
When I do this, I retrieve the main record OK, but the child records are NOT retrieved.
This is true if I run the code against SQL Server as well as Effort (so it's not Effort).
If I dispose the context and create a new one, the same method retrieves the data correctly include the children.
So something about clearing the local cache is interfering with the data retrieval. I've tried clearing just cache for the main record and also for both that and the child records - no difference.
Any suggestions would be appreciated.

Saving a doctrine2 entity to cache to speed up the page load

Let's say I have an entity called Product and this entity is loaded every time user hits the product information page. Usually I'd save the object in Zend_Cache (memcache) for an hour to avoid hitting the db for each request but as far as I understand that's not possible with Doctrine2 entities because of the Proxy objects.
So my question is, how can I avoid loading the same entity from the database for each request?
[EDIT]
I tried using Doctrine Cache like this
$categoryService = App_Service_Container::getService('\App\Service\Category');
$cache = $categoryService->getEm()->getConfiguration()->getResultCacheImpl();
$apple = $cache->fetch('apple');
But I get the following error
Warning: require(App/Entity/Proxy/_CG_/App/Entity/Category.php)
[function.require]: failed to open stream: No such file or directory
in /opt/vhosts/app/price/library/Doctrine/Common/ClassLoader.php on
line 163
This is same for Zend Cache as well as you can't serialize the entity because of the Proxy class
You've got several options:
Use Doctrine's built-in result caching
Try just sticking entity in memcache via Zend_Cache. When you pull it out, you may need to merge() the Product back into the EM so proxies can be dereferenced. If you fetch-join any associations you need to display the product info, and you're only doing reads, this shoudl work fine.
Don't cache the entity at all. Cache whatever output you generate instead.
EDIT: If you don't care about the hydration overhead, you're using mysql, and your Products and associated tables don't change very often, you might prefer to just rely on the mySQL query cache. It's a fairly blunt object, but useful enough to mention.
You might want to try implementing __sleep or __wakeup methods for your entity class, as Doctrine 2 has special requirements and limitations concerning serialization/deserialization of entities (which is what happens when storing them in Zend_Cache).
There is this guidance.
General information about limitations including serialization.
I find this extremely strange since i just messed around with this myself and didn't have any issues with the proxy object being stored in the database. So im guessing your configuration is not setup 100% ?
If you find the issue with your configuration then be very aware of what timdev said you MUST merge the object back into the EntityManager else you will have weird bugs down the line.
A fourth solution available for you is also to retrieve the data as an array instead of an object, but then of course you lose all the functionality connected to your module which might not be exactly want you wanted.
It seems to me more like a configuration error. Either Proxies have not been generated or there is something wrong with the proxy directory and namespace.
Depending on your configuration, proxies can be either generated automatically or manually. Does your proxies have been indeed generated under App/Entity/Proxy ? Is this indeed the right directory?
FYI proxies can be manually generated by executing doctrine orm:generate-proxies <dest-dir>
Seconding what timdev says: Doctrine has built-in caching, you want to use it.
I also wonder from your question if you are experiencing any performance issues or if you are a victim of overly eager optimisation.

Entity Framework - avoiding another query

I have a requirement to only save data to a table in a database (I don't need to read it)
If the record already exists I want to update it otherwise I will add it.
It usually exists.
My entity context might already hold the object .. if it does I want to find it and use it again without causing it to refresh from the database when I 'find' it
i.e. The context holds a collection of entities (rows of a database) I want to find an entity in the collection and only want the context to go to the database if entity is not in the collection. I don't care about the current values of the entity .. I just want to update them.
Hope this is clear ..... thanks
I may not be quite seeing the question, but I believe your looking for some sort of caching mechanism, I know for work we use devForces IdeaBlade which does the trick, however I believe you can create a simple caching mechanism custom to you needs.
Link
The bits on caching will be helpful, if this doesnt help tell me and I can dig a little deeper.
I believe you need to use GetObjectByKey() instead of using an ObjectQuery I believe an ObjectQuery always hits the backend datastore whatever it may be.
More Info here http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.getobjectbykey.aspx