Reputation: 5662
When I make a request to my Servlet
, it checks the database for any updated Entities
(I am using JPA for that). The updated Entity
is then fetched and the Servlet
is supposed to return the entity as a JSON String. But I am getting an old version of the entity, one that has not been updated yet – although I can see the underlying MySQL database already has the updates. How is this possible? Am I missing any buffers or caches?
This is my architecture / the data flow:
––––––-- timestamp of previous request ----------–––
| client |–––––––––––––––––––––––––––––––––>| PullServlet |
-------- (e.g. 1475056871050) -------------
|(injected)
|
-------------------- ---------------
| Entity Facade |<----| remote |
| implementation | | Entity Facade |
-------------------- ---------------
|
@NamedQuery
| SELECT m
| FROM MyEntity m
| WHERE
| m.updated >=:previousRequest
Let's say the row in the MySQL database looks like this:
id | updated | value
---+---------------+--------
12 | 0 | "hi"
Then an update is made and the updated
column logs the time in milliseconds when the update was made:
id | updated | value
---+---------------+--------
12 | 1475056872002 | "hello"
so the query SELECT ... WHERE 1475056872002 >= 1475056871050
returns the entity because the updated
column¹ has a value that is greater than the previousRequest
parameter.
However when I log the result of the query, I get something like this
id=12, updated=0, value="hi"
instead of
id=12, updated=1475056872002, value="hello"
And the old row gets send to my Servlet, which then sends the old version as JSON to my client:
{
"id" : 12,
"updated" : 0,
"value" : "hi"
}
Question: is there any cache that I could "flush" or anything, to make sure that the selected rows are always up to date?
So I added some logging and this is the result:
Facade makes update
UPDATED entity: id=45111, updated=1475067494578, value=100
Client makes request to servlet a few seconds later
Client requested update – fetching entities // servlet
Facade fetched update: id=45111, updated=1475066854564, value=96 // Facade
servlet received update: id=45111, updated=1475066854564, value=96 // servlet again
Client receives JSON
{
"id": 45111,
"updated": 1475066854564,
"value": 96
}
Thanks to Navneet Arora I found out that the entites where indeed cached and the query used those cached instances instead of retrieving the entites from the database. This Answer from another question shows how ignore the cache.
Now my query looks like this:
TypedQuery<Post> query = getEntityManager().createNamedQuery("MyEntity.getUpdatedSince", MyEntity.class);
query.setParameter("previousRequest", previousRequest);
query.setHint(QueryHints.REFRESH, HintValues.TRUE); //this does the trick
And now everything is fine and I get all the updates :)
__________________
¹ the updated
column and the previousRequest
parameter are unix timestamps in milliseconds
Upvotes: 0
Views: 266
Reputation: 20
In your calling code, you can check if your entity is available in cache or not. If it is available with older value, you can clean it using evict or evictAll method and then try to retrieve values. Following are some sample coding statements for your reference:-
javax.persistence.Cache cache = entityManagerFactory.getCache();
System.out.println("cache.contain should return true if entity exists in cache: "+cache.contains(Order.class, order.Id()));
With following code, you can remove entity from cache, if it exists there:
cache.evict(Order.class);
Upvotes: 1