Retrieving Old Data Using JPA

I get old data with JPA even if I disable the cache. I think this is because the resource is set to RESOURCE_LOCAL, but I'm not sure.

<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="AppPU" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>com.myentities.User</class> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/mydatabase"/> <property name="javax.persistence.jdbc.password" value="*****"/> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="javax.persistence.jdbc.user" value="user1"/> <property name="eclipselink.logging.level" value="FINEST"/> </properties> </persistence-unit> </persistence> 

My code that gets old user information:

 public List<User> findAll(App app) { getEntityManager().getTransaction().begin(); Query q = getEntityManager().createQuery("SELECT t1 FROM User t1 WHERE t1.app.idApp=:idApp"); q.setParameter("idApp", app.getIdApp()); getEntityManager().flush(); getEntityManager().getTransaction().commit(); List resultList = q.getResultList(); return resultList; } 

My essence:

 @Entity @Table(name = "user") @Cache ( type=CacheType.NONE ) public class User implements Serializable { // some attributtes } 

Does anyone know what is going on?

UPDATE 1

The start, flush and fix methods were just despair! I know this is not necessary.

I forgot to say something important : the test I am doing is adding a direct user entry to the database console , and then try to view it through my webapp, which is not showing a new user . This is the "old data" that I mentioned, it displays only the "old users".

I already tried putting this on persistence.xml and I did not see any difference in the results:

 <property name="eclipselink.cache.shared.default" value="false"/> <property name="eclipselink.cache.size.default" value="0"/> <property name="eclipselink.cache.type.default" value="None"/> 

So something else and hellip;

+6
source share
6 answers

Several suggestions have already been published, for example, to disable the shared cache and manage backlinks so that the cache is consistent. This applies to specific situations that may occur, but you have not provided enough to say what is actually happening.

Another that is specific, but seems possible based on using getEntityManager (), is to reuse an EntityManager instance without clearing it. EntityManager contains references to all managed objects, since EM is required to return the same instance to a subsequent request and look up calls to support authentication.

If this is not already done, you need to clear the EntityManager or get a new one at certain points to free up memory and managed objects.

+16
source

First of all, do not use

 @Cache(type=CacheType.NONE) or, <property name="eclipselink.cache.size.default" value="0"/> or, <property name="eclipselink.cache.type.default" value="None"/> 

just install

 @Cache(shared=false) or, <property name="eclipselink.cache.shared.default" value="false"/> 

Secondly, where did your EntityManager come from? Are you creating a new transaction request? If you do not, everything read in the EntityManager will be in the cache (L1). You need to call clear () or create a new one.

+3
source

Using

 <property name="eclipselink.cache.shared.default" value="false"/> <property name="eclipselink.cache.size.default" value="0"/> <property name="eclipselink.cache.type.default" value="None"/> 

or

 @Cache(shared=false) 
+1
source

Unlike the answer to caching (which I will have to try), you are likely to come across a situation where your reference object is not updated.

 @Entity Class Parent { @OneToOne(Cascade.ALL)//Or only Merge, whatever you're needs Child child; } @Entity Class Child { Parent parent; ... Values } 

When saving the Child, you need to update your link to the parent so that the memory model (cache) matches the database. This is rather unpleasant, but the way I did it was to cascade only from the parent.

 public void saveChild(Child child) { child.getParent().setChild(this); //or DTO Code, whatever EntityManager.merge(parent); //cascades to the child. //If you're manually cascading (why?) //EntityManager.merge(child); } 

This will be cascaded if you configure it โ€” I saw that the reverse cascade (child merge causes the parent cascade) was not reliable - due to my lack of knowledge in the subject.

In short - if you handle the merge in your data core, the problem goes away. I do not want to disable caching, as this can have a significant impact on large applications, so I went this way. Good luck, and please tell us your approach.

+1
source

1) Specify the code

 public List<User> findAll(App app) { Query q = getEntityManager().createQuery("SELECT t1 FROM User t1 WHERE t1.app.idApp=:idApp"); q.setParameter("idApp", app.getIdApp()); List resultList = q.getResultList(); return resultList; } 

2) Remove @Cache (type = CacheType.NONE) from the entity class

3) No need to change persistence.xml

0
source

Using EntityManager is the key. I reached the perfect solution after several months:

  • Use the general DEFAULT object manager for all READINGS of the object. This means creating a separate object manager for each object.
  • Create a new entity manager for each write / update / delete operation of each object. Use begin / commit to transaction this new object. Close the object manager after the operation is completed.
  • Node item: clear the DEFAULT object manager (reader one) after you commit and close the write entity manager. This means only after recording; not before every reading.
0
source

Source: https://habr.com/ru/post/900314/


All Articles