I have tried disabling L2 cache in EclipseLink with Eclipse indigo by using following properties in persistence.xml:-
<property name="eclipselink.cache.shared.default" value="false"/>
<shared-cache-mode>NONE</shared-cache-mode>
Basically I am testing one scenario whether same object created in two different sessions is hitting database twice or both sessions are referring to same object created in earlier session in memory cache. It should not because L2 cache is disabled by mentioning above properties in persistence.xml
My code is as below:-
Session session = DataAccessManager.getManager().openSession();
ReferenceObjectRepository referenceObjectRepository = ReferenceObjectRepository.getInstance();
ReferenceObjectKey referenceObjectKey = new ReferenceObjectKey(getStringValue("testCacheByPass.input"));
//load object first time.
ReferenceObject referenceObject = referenceObjectRepository.load(ReferenceObject.class, referenceObjectKey);
logger.log(Level.SEVERE, "Cache ReferenceObject: " + referenceObject);
//load object in another session
Session sessionNew = DataAccessManager.getManager().openNewSession();
Object dbObject = referenceObjectRepository.load(ReferenceObject.class, referenceObjectKey);
logger.log(Level.SEVERE, "DB loaded ReferenceObject: " + dbObject);
Please help me whether I have missed something? or do I need to do it some other way??
Add this line in each function where the call is made. I use in the find function when consulted a view.
((JpaEntityManager)em.getDelegate()).getServerSession().getIdentityMapAccessor().invalidateAll();
This line clear the cache before run de query.
public Entity find(Object id) {
((JpaEntityManager)em.getDelegate()).getServerSession().getIdentityMapAccessor().invalidateAll();
return em.find(Entity.class, id);
}
You have disabled the object cache, but I think you still have query cache in play. You should be able to disable query cache too with
<property name="eclipselink.query-results-cache" value="false"/>
<property name="eclipselink.refresh" value="true"/>
Same thing can be set with query hints, too. You could also try using query hints if persistence.xml configuration doesn't seem to be working.
Also note that essentially, even without the caching, you'd be comparing the same object, so unless it is detached it should be the same.
Related questions:
Disable eclipselink caching and query caching - not working?
Disable caching in JPA (eclipselink)
Related
With Wildfly 16, using the EntityManager I persist a new entity and invoke another routine to perform an HQL query to retrieve that entity, but it fails to return.
This is running server side and is normally triggered by a client command. The command should cause the new object to be persisted, then call a routine used in several places that selects objects (like and including the newly persisted one) and format and push them to subscribers.
I've tried a few things to get this working:
Flush the EntityManager prior to the HQL query
Reuse the EntityManager via the invoked routine (with and without flushing post persist())
The only way I've managed to get the desired results is to cause the initial client command to persist the entity, then perform a second client command to retrieve the entity persisted via the first command. This is not an issue with the HQL retrieving the data as it does work - it just doesn't work immediately after persisting the entity. It seems like either the data isn't persisted prior to the HQL query or the HQL query is looking at something cached (although I haven't specifically set anything like that, so it would have to be a default I'm unaware of).
An example of the three routines:
//Routine A - calls B & C
routineB();
routineC();
//Routine B
EntityManager em = emProvider.getEntityManager(); //pulls em from a stateless bean tagged #PersistenceContext
Blah blah = new Blah();
em.persist(blah);
em.flush();
//Routine C
EntityManager em = emProvider.getEntityManager();
List<Blah> blahs = em.createNamedQuery("retrieveBlah").getResultList();
//do some stuff with blahs... except it's missing blah from Routine A
My persistence.xml settings JIC that's relevant
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL94Dialect" />
<property name="hibernate.connection.useUnicode" value="true" />
<property name="hibernate.connection.characterEncoding" value="UTF-8" />
<property name="hibernate.connection.charSet" value="UTF-8" />
<property name="hibernate.id.new_generator_mappings" value="true" />
I need to be able to persist and retrieve the persisted via HQL query as the result of a single client command.
It turns out the post above was missing the key bit of information to resolve the issue. After posting this I continued testing and discovered the piece I overlooked, "routineB()" was marked #Asynchronous. So it was executing in parallel to routineC().
I am facing some problem in OpenJpa second level caching. Most of times caching is working but in one particular case it is not working. Here is a scenario when it is not working,
When your code result null value then it store it into cache and then it never clear that value. Although it clears values only when query returns a value.
Here is code which I had written to get value from database,
List<PartnerapiworkflowEntity> partnerapiworkflowEntityList = null;
try {
partnerapiworkflowEntityList = entityManager.createQuery("select p from someentity p where p.id = :Id and p.name = :name and " +
"p.code = :Code and p.operationname = :operationName")
.setParameter("Id", Id)
.setParameter("name", name)
.setParameter("code", Code)
.setParameter("operationName", operationName).getResultList();//.getSingleResult();
if(partnerapiworkflowEntityList != null && partnerapiworkflowEntityList.size() > 0){
return Boolean.TRUE;
}
} catch (NoResultException ne) {
logger.severe("some logging info.");
}
finally {
// entityManager.detach(partnerapiworkflowEntity);
}
And here is a code which refresh cache.
try{
entityManager.flush();
entityManager.clear();
entityManager.getEntityManagerFactory().getCache().evictAll();
//((JpaEntityManager)entityManager.getDelegate()).getServerSession().getIdentityMapAccessor().invalidateAll();
entityManager.flush();
} catch (Exception e){
throw e;
}
And this is persistence.xml code
<property name="openjpa.jdbc.DBDictionary" value="mysql"/>
<property name="openjpa.DataCache" value="true(EnableStatistics=true, CacheSize=10000, SoftReferenceSize=0, EvictionSchedule='+10')"/>
<property name="openjpa.QueryCache" value="true(EvictPolicy='timestamp')"/>
<!--<property name="openjpa.jdbc.QuerySQLCache" value="true(EnableStatistics=true)"/>-->
<property name="javax.persistence.sharedCache.mode" value="ENABLE_SELECTIVE"/>
<property name="openjpa.Instrumentation" value="jmx(Instrument='DataCache,QueryCache,QuerySQLCache')"/>
<property name="openjpa.MetaDataRepository" value="Preload=true"/>
<property name="openjpa.Log" value="SQL=Trace" />
<property name="openjpa.ConnectionFactoryProperties" value="PrintParameters=true" />
Everything working fine when query always returns value. The problem is start when it return null value. Then first time is store in cache and then it never refresh.
I am using OpenJpa2 and Hibernate.
This issue was first observed with OpenJPA 2.2.2. Looking up online revealed that there was a defect that was fixed on trunk that was related to L2 cache (https://issues.apache.org/jira/browse/OPENJPA-2285)
But this problem is again found later in https://issues.apache.org/jira/browse/OPENJPA-2522
Solution:
So far it is not fixed yet. But they have given some bypassing solution.
Disable query cache
To disable the query cache (default), set the openjpa.QueryCache property to false:
<property name="openjpa.QueryCache" value="false"/>
By configuring sql query cache to false
To specify a custom cache class:
<property name="openjpa.jdbc.QuerySQLCache" value="com.mycompany.MyCustomCache"/>
To use an unmanaged cache:
<property name="openjpa.jdbc.QuerySQLCache" value="false"/>
OR
To use an unmanaged cache:
<property name="openjpa.jdbc.QuerySQLCache" value="all"/>
Open JPA - L2 Cache Issue and Workaround
This tutorial depicts your problem same to same. Here you can get the
clear conception of occuring this error.
It gives a solution that you must have to keep related data. So that NullPointerException will not arise. Data must be consistent until OpenJPA not solve the issue. :D
Several mechanisms are available to the application to bypass SQL
caching for a JPQL query.
A user application can disable Prepared SQL Cache for entire lifetime of a persistence context by invoking the following method on OpenJPA's EntityManager SPI interface:
OpenJPAEntityManagerSPI.setQuerySQLCache(boolean)
Plug-in property openjpa.jdbc.QuerySQLCache can be configured to
exclude certain JPQL queries as shown below.
<property name="openjpa.jdbc.QuerySQLCache" value="true(excludes='select c from Company c;select d from Department d')"/>
will never cache JPQL queries select c from Company c and select d from Department d.
Root Cause Analysis:
The query cache stores the object IDs that are returned by query executions. When you run a query, JPA assembles a key that is based on the query properties and the parameters that are used at launch time and checks for a cached query result. If one is found, the object IDs in the cached result are looked up, and the resulting persistence-capable objects are returned. Otherwise, the query is launched against the database and the object IDs that are loaded by the query are placed into the cache. The object ID list is not cached until the list that is returned at query launch time is fully traversed.
IBM Recommendation:
L2 caching increases the memory consumption of the application,
therefore, it is important to limit the size of the L2 cache. There is
also a possibility of stale data for updated objects in a clustered
environment. Configure L2 caching for read-mostly, infrequently
modified entities. L2 caches are not recommended for frequently and
concurrently updated entities.
Resource Link:
Open JPA 2.4.0 Caching Reference Guide
You are evicting entries, but what about query cache? It can be that in normal case evicting is noticed by query case, so the result is invalidated... It can explain why null fails here. Can you please confirm?
EDIT:
<property name="openjpa.QueryCache" value="false"/>
Means no query cache. My bad.
Other try - NULL check? You have query, with params - can you execute it directly on the database?
I am using spring and hibernate application, In my requirement I have to load data from database at the time of project deployement and store data in Map or List for further use in whole application. I have googled a lot but not found any solution.
try using a ServletContainerInitializer
https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6/html/API_Documentation/files/javadoc/javax/servlet/ServletContainerInitializer.html
If this ServletContainerInitializer is bundled in a JAR file inside the WEB-INF/lib directory of an application, its onStartup method will be invoked only once during the startup of the bundling application.
You can use
<prop key="hibernate.cache.use_query_cache">true</prop>
In hibernate configuration.xml
to cache the data that you access from data base and store in object ... now if you use the same object anywhere in your application it will use the same cache and wil not hit the database again.
Another way is
you can configure the cache using the xml file, see the spring reference manual:
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/cache.html#cache-declarative-xml
<!-- the service we want to make cacheable -->
<bean id="service" class="x.y.service.MyService"/>
<!-- cache definitions -->
<cache:advice id="cacheAdvice" cache-manager="cacheManager">
<cache:caching cache="books">
<cache:cacheable method="getData" key="#id"/>
<cache:cache-evict method="loadData" all-entries="true"/>
</cache:caching>
</cache:advice>
<!-- apply the cacheable behaviour to all dataService interfaces -->
<aop:config>
<aop:advisor advice-ref="cacheAdvice" pointcut="execution(* x.y.myService.*(..))"/>
</aop:config>
Better approach is to use Hibernate, In hibernate we have First Level cache.
First-level cache always Associates with the Session object. Hibernate uses this cache by default. Here, it processes one transaction after another one, means wont process one transaction many times. Mainly it reduces the number of SQL queries it needs to generate within a given transaction. That is instead of updating after every modification done in the transaction, it updates the transaction only at the end of the transaction.
First level cache retrieval example
In this example, I am retrieving DepartmentEntity object from database using hibernate session. I will retrieve it multiple times, and will observe the sql logs to see the differences.
//Open the hibernate session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
//fetch the department entity from database first time
DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());
//fetch the department entity again
department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());
session.getTransaction().commit();
HibernateUtil.shutdown();
Output:
Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource
Human Resource
As you can see that second “session.load()” statement does not execute select query again and load the department entity directly.
If you need to load the collection at time of class loading you can make use of immediate fetching or eager loading strategy in Hibernate. According to eager loading, when you make any collection as eagerly loaded lets suppose-->
If Foo has a Collection, and you set it to lazy, then only when you need the contents fo that collection are the selected, loaded, etc. whereas if it is eager, it will load the Bars at the time it loads Foo. This can be problematic if you eagerly load a collection of entities that eagerly load a collection of entities, and so on.
But I suppose in your case the Fetch Type = eager strategy will work and it will load at the time the class is loaded.
An Example :
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#JoinColumn(name="countryId")
private Set states;
First of all you can't use any List or Map as Cache replacement. You can use Hibernate Second Level Cache, or even an external caching solution as long as your data is not going to be modified, which might cause consistency issues.
So if teh cached data is read-only then you can safely cache it. Otherwise you need a read-write cache, and the second Level Cache is much more appropriate in this scenario.
I am using Hibernate 3.2.5 for my application. I am trying to implement Query Cache but it is not working.
Problem Description:
For the first time, the DB is hit, data is fetched and cached. For the second time, for the same query again the DB is hit rather than taking the data from the cache. For the second time, I want it to take it from the cache rather than hitting the DB again.
For enabling the Query Cache, I made the below entries in the cfg.xml file:
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
Created the file: ehcache.xml and added the below entry in the hbm.xml files:
<cache usage="read-only" />
Below is the code I tried:
SessionFactory sf = new Configuration().configure("trial.cfg.xml").buildSessionFactory();
Session session = sf.openSession();
List departments1 = session.createQuery("from Dept dept where dept.deptId = 1")
.setCacheable(true)
.setCacheRegion("departmentId")
.list();
//Some business operations
session.flush();
session.close();
//Some business operations
Session session1 = sf.openSession();
List departments2 = session1.createQuery("from Dept dept where dept.deptId = 1").list();
//In the above line again it is hitting the DB rather than taking it from the cache.
I believe that I am missing something for which it is not fetching the data from the cache and hence hitting the DB. Kindly let me know how to make this Query Cache work.
The second query is not cacheable, so it doesn't use the cache. As simple as that.
Note that if this is your real code, you should simple use session.get(Dept.class, 1) to get the department.
Taking following code:
MyEntity e = dao.getEntity(1);
e.setProp1(someVal);
e.setProp2(otherVal);
MyEntity eOld = dao.getEntity(1);
If I do it like this then e will get updated (because Hibernate detected it is dirty) and eOld will have the same property values (prop1, prop2) a e. Is there a way to get the persisted state of this dirty entity (as it is in the database)?
Try:
<property name="defaultAutoCommit" value="false" />
Or alternative use detach and re-attach when ready to persist.
dao.detach(e);
...
e.setProp1("AnotherVal"); //not propatated to the database
dao.merge(cat); // update
Actually I may already have found the solution myself...
I had already tried evicting eOld but that doesn't make since, I need to evict e before retrieving eOld and after the compare (for auditing) reattach (merge) e to the session again.
It seems to work in any case.