0
votes

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.

  1. How can I not use cache for a single stored procedure call with Eclipselink?

  2. Bonus: Why would a stored procedure call that returns a null user be cached?

2

2 Answers

1
votes

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

0
votes

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);