HibernateTemplate findByNamedQueryAndNamedParam very slow - spring

I am working on a new project on some existing code . It uses HibernateTemplate.findByNamedQueryAndNamedParam to invoke a stored procedure in the database .
When I execute the stored procedure on the database , it executes in 2 or 3 seconds . But I execute it via the HibernateTemplate method , it takes anywhere between 2 to 34 minutes .
When I turn showsql on , I see that there are thousands of select statements being triggered . Any pointers on possible reasons for why this could happen .

Your problem may be caused by a bad configuration of 2nd level cache and query cache.
Check that expiration time of your query cache is the same as the expiration time for the 2nd level cache - for all entities fetched by your query -. (look into ehcache config file -or any other 2nd level cache provider you are using-)

Related

Hibernate first level cache to hold entities found by a property that is not the ID

I am working on a Java 8 / Spring Boot 2 application and I have noticed that the security module of my app internally uses the findByEmail method of my UserRepostiory (which is a standard Spring Data JPA Repository). When I enabled Hibernate SQL logging, I discovered that these queries are performed multiple times within the same session (security uses it 3-4 times and then my business code uses it some more times). Each time the query hits the database.
This surprised me, as I expected it to be cached in the Hibernate's first level cache. After reading up about it a little bit more, I found out that the first level cache only caches the result of the findById query, not others.
Is there anyway that I can cache the result of the findByEmail query in the first level cache? (I don't want the cache to be shared between sessions, I don't want to use the 2nd level cache, as I think it should be invalidated right after the current session ends).
Yes, you can cache the results of a query on a unique property if you annotate the property with the #NaturalId annotation. If you then use the dedicated API to execute the query, the results will be stored in the 1st level cache. An example:
User user = entityManager
.unwrap(Session.class)
.bySimpleNaturalId(User.class)
.load("john#example.com");

update ignite cache with time-stamp data

My issue is that how to update cache with new entries from database table?
my cache has my Cassandra table data suppose for till 3 p.m.
till that time user has purchase 3 item so my cache has 3 items entry associated with that user.
But after sometime (say 30min) what if user purchase 2 more item ?
As i have 3 entry in cache it wont query from database, how to get those 2 new entry at time of calculation final bill.
One option i have is to call cache.loadCache(null, null) every 15 min? but some where this is not feasible to call every time?
The better option here is to insert data not directly to Cassandra, but using Ignite. It will give a possibility to have always updated data in the cache without running any additional synchronizations with DB.
But if you will choose to run loadCache each time, you can add a timestamp to your object in DB and implement your own CacheStore, which will have addition method that will load only new data from DB. Here is a link to the documentation, it will help you to implement your own CacheStore.

Update database records based on date column

I'm working on a app where I have some entities in the database that have a column representing the date until that particular entity is available for some actions. When it expires I need to change it's state, meaning updating a column representing it's state.
What I'm doing so far, whenever I ask the database for those entities to do something with them, I first check if they are not expired and if they are, I update them. I don't particularly like this approach, since that means I will have a bunch of records in the database that would be in the wrong state just because I haven't queried them. Another approach would be to have a periodic task that runs over those records and updates them as necessary. That I also don't like since again, I would have records in a inconsistent state and in this case, the first approach seems more reasonable.
Is there another way of doing this, am I missing something? I need to mention, I use spring-boot + hibernate for my application. The underlying db is Postgresql. Is there any technology specific trick I can use to obtain what I want?
in database there it no triger type expired. if you have somethind that expired and you should do somethig with that there is two solutions (you have wrote about then) : do some extra with expired before you use data , and some cron/task (it might be on db level or on server side).
I recomend you use cron approach. Here is explanation :
do something with expired before you get data :
updated before select
+: you update expired data before you need it , and here are questions - update only that you requested or all that expired... update all might be time consumed in case if from all records you need just 2 records and updated 2000 records that are not related you you working dataset.
-: long time to update all record ; if database is shared - access to db not only throth you application , logic related to expired is not executed(if you have this case); you need controll entry point where you should do something with expired and where you shouldn't ; if time expired in min , sec - then even after you execure logic for expired , in next sec new records might be expired too;also if you need update workflow logic for expired data handling you need keep it in one plase - in cron , in case with update before you do select you should update changed logic too.
CRON/TASK
-: you should spend time to configure it just once 30-60 mins max:) ;
+: it's executed in the background ; if your db is used not only by your application , expired data logic also be available; you don't have to check(and don't rememebr about it , and explaine about for new employee....) is there any staled data in your java code before select something; you do split logic between cares about staled data , and normal queries do db .
You can execute 'select for update' in cron and even if you do select during update time from server side query you will wait will staled data logic complets and you get in select up to date data
for spring :
spring scheduling documentation , simple example spring-quartz-schedule
for db level postgresql job scheduler
scheduler/cron it's best practices for such things

How to refresh iBatis Cache with database operations

We have an Java EE web application using iBatis for ORM. One of the dropdown (select box) shows a master data which is refreshed on a daily basis (say 4.00 AM) via cron jobs loading flat file into oracle database table.
Since the dropdown/select-box has to list ~1000 records and it was static data for 24 hrs, we used the CacheModel feature in iBatis. The select query was made to use a CacheModel with settings "ReadOnly=true & Serialized=true flushInterval=24 hours", so that a single cache will be shared across all users.
There will no insert/update/delete operations happening from the application to modify this master data
Question:
If the external job loading data to this oracle table fails and if the iBatis cache is flushed for the day before we manually load the data in the table, how can i get the iBatis cache flushed again inbetween of the day when i rerun a failed cron job ?
Please note that, there will not be any Insert/Update/Delete operations from the application
You can flush cache programmatically.
There are 2 methods
void flushDataCache()
Flushes all data caches.
and
void flushDataCache(java.lang.String cacheId)
Flushes the data cache that matches the cache model ID provided.
in SqlMapClient interface.
http://ibatis.apache.org/docs/java/user/com/ibatis/sqlmap/client/SqlMapClient.html

performance issue in find() method after migration to Hibernate 4.0 from OpenJPA 1.2

I migrate from OpenJPA 1.2 to Hiberante 4.0
I'm using TimesTen DB
I'm doing a native query to get id's of object's that I need , and then perform find on each on of them.
In OpenJPA instead of find I used findCache() method and if it return null I use the find() method , In hibernate I used only the find() method.
I performed this operation on the same DB.
after running couple of test I saw that the performance of OpenJPA is far better.
I printed the statistics of hibernate session ( after querying and finding the same object's) and saw that the hit\miss count to the first level cache is always 0.
while the OpenJPA is clearly reaching it's cache by fetching object's with the findCache method.
How can I improve the performance of find in Hibernate ?
I suspect it referred to the difference in the first level cache implementation of this tools.
another fact: I use the same EntityManager for the application run time ( I need to minimize the cost of creating of an EntityManager - my app is soft real time )
thanks.
Firstly, why don't you just retrieve the full objects instead of the id. One select statement to retrieve a number of objects is many magnitude times faster than retrieving each item individually.
Secondly, you likely need a second level cache for hibernate. The first level cache is mostly applicable within each session.
The first level cache in Hibernate corresponds to the session. So if the session has not yet loaded a given object, it will be a miss.
You need to enable second level cache to be able to cache an object by id across sessions.
Check out the reference documentation for more info http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/#performance-cache

Resources