Hibernate transaction problem - java

When I execute some queries inside Hibernate transaction -> the data successfully updated in my mysql, but in my application there are still old values. When i restart - it`s Ok. If i set autocommit mode - works fine, but i have to use transaction ;-). Any ideas?
Thanks in advance.

Manipulating the database directly with UPDATE doesn't affect the objects cached in the session. You should clear the session (Session.clear()). Something like:
session.flush()
session.clear()
query.executeUpdate()
Or even better, you can avoid the problem by not using update queries and manipulating the object state in memory:
myobj.setName(newValue)
session.saveOrUpdate(myobj)

In hibernate either you are using JPA API or Hibernate's native API any query that you run using below interface
Criteria (Hibernate Native API)
Query (Hibernate Native API)
EntityManager createQuery() (JPA)
The queries dont interact with the second level or first level cache . They directly hit the database .If your query is updating the entities currently in the persistence context , those entities will not reflect the changes.This is the default behavior.
In order to update your context to show the latest state of entity use the refresh() in Session or in EntityManager to reflect the latest entity state in persistence context.
Read the docs below for more info
http://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#refresh-java.lang.Object-
https://docs.jboss.org/hibernate/orm/3.5/javadocs/org/hibernate/Session.html#refresh%28java.lang.Object%29
Otherwise as a convention always run your DML before loading any data in the persistence context.
Hope this helps :D

Related

SpringData JPA is not refreshing or clear the cache, when table is updated from outside resource

I'm working on SpringBoot Jpa to interact with DB tables, in few of my JPA repository I am getting old version of JPA Entity(Not Updated) when other applications updated that particular database table from outside, JPA is not able to give updated dataset. I tried using EntityManager.clear(), entityManager.getEntityManagerFactory().getCache().evictAll(); but not of them working.
At the end, I had to create a new entityManager object from entityManagerFactory and run the native SQL to get the updated output. But this is not a good practice for my project as it makes my JPA dependent on Native SQL. So, please let me know if there is anything I am missing or should do to reflect the latest changes from my JPA repository at run time.
Or is there any way from which I can run JPA repository from newly created entitymanager object?
entityManager.getEntityManagerFactory().getCache().evictAll(); //Autowired from persistenceContext
entityManager.clear();
EntityManager em=emf.createEntityManager();
Try adding #Transactional annotation to the Service.
Also, make sure you're having a single entity instance.
I think you should add the bellow code:
entityManager.flush();

Hibernate query already fetched entities

Is there a way in hibernate(or ORM in general) to query session managed collections, i.e get entity with max id, without hitting the database.
Right now I do this with Java stream API. It works and it is much faster than a database query. But I find myself doing this a lot in my current project. So I thought hibernate might already have an option to run queries "locally".
It is an desktop application so i am sure the DB won't change outside of this application.
No #lazyCoding, HIBERNATE can't do it. Maybe http://josql.sourceforge.net/manual/introduction.html will help you.

Debugging JUnit Tests in a Hibernate driven Spring Application

Maybe this has been answered already, but i did not find any suggestions out there...
My Project is a Spring Utility Project, the database i use is MySQL and for persistence i´m using Hibernate in combination with c3p0 connection pooling. i´m on spring 3.2 and hibernate 3.5.
So here is what i want to do:
I want to debug a JUnit test, step over some persistence functions (save, update, etc. ) and then check the entries manually in the database via SQL. Because of the JUnit tests always running in a transaction, i cannot check the entries in the database, because a rollback happens every time a test finished / a commit never occurs.
Is there a way to fake transaction existence, or bypassing them during JUnit tests?
Perhaps you can flush the transaction in Hibernate during your debugging session and force Spring/Hibernate to write to the database.
Or you can turn off transactions for your debugging session.
Rather than fake transaction existence, the best approach to looking at the database while the transaction is taking place is to query with an isolation level that allows dirty reads. The mechanism for doing this varies from database to database, and in MySQL you can use
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
prior to querying.
Clearly you will also need to force Hibernate to flush writes to the database during your test, and set your breakpoint after the flush.

Needs clarity on hibernate second level cache

I need some clarification with the Hibernate second level cache.
How does the hibernate second level cache works?
Does it loads all the data from the tables for which there is #Cacheable annotation (with respect to hibernate annotation) in the entity classes on server start up in the Java EE environment?
Will the cache gets sync up when there is an update on those tables and how?
Last one is there any ways for my DAO code to get notified when there is an updated on some table which i am interested upon? (Looking for any listener which can intimate abt the updates of the tables).
How does the hibernate second level cache works?
When your entity is marked as cacheable and if you have configured the second level cache then hibernate will cache the entity to the second level cache after the first read.
Hibernate provides the flexibility to plugin any cache implementation that follows hibernates specification. Refer Hibernate Manual for more details on second level cache and configurations options.
Does it loads all the data from the tables for which there is #Cacheable annotation (with respect to hibernate annotation) in the entity classes on server start up in the Java EE environment?
I don't think there is any configuration for achieving this. Indirectly you can achieve this by reading the entire table in startup, this can adversely affect the system startup time. (i don't prefer this). If the entity is modified externally, then hibernate can't sync it and you will end up getting stale data.
Will the cache gets sync up when there is an update on those tables and how?
The cache won't get updated instantly after the table update. The subsequent call to fetch the updated record will go the database, hibernate achieves this internally by using session timestamps.
Last one is there any ways for my DAO code to get notified when there is an updated on some table which i am interested upon? (Looking for any listener which can intimate abt the updates of the tables).
No, hibernate doesn't support this.
That's a too broad question to be answered here.
No. It populates the cache lazily. Each time you get a cachable entity from the database, using the hibernate API or a query, this entity is stored in the cache. Later, when session.get() is called with an ID of an entity that is in the cache, no database query is necessary.
If the update is made through Hibernate, then the cache is updated. If it's done using an external application, or a SQL query, or even a bulk update HQL query, then the cache is unaware of the update. That's why you need to be careful about which entities you make cachable, which time-to-live you choose, etc. Sometimes, returning stale values is not problematic, and sometimes it is unacceptable.
No.

Weblogic + JPA don't refresh data on Oracle database

I have a system based on Oracle10g (datasource) + Weblogic 10.3 + Eclipselink.
If I insert or delete data via the Java software with DAOs, all the data are immediately avaliable, but if I manually insert data (via SqlDeveloper or using the java.sql.Connection class), the new data are not brought from database.
Why it happens? And how to fix it?
It happens because EclipseLink cannot be aware that changes are made to database via some other methods. External tools do not inform EclipseLink about changes and EclipseLink is not all the time polling database content for possible changes. Such a implementation would kill performance. Same happens also with changes made via JPA bulk operations, like JPQL and native SQL DELETE and INSERT queries.
You cannot really fix the problem, but it is easier to live with it, when you turn of shared cache. Be aware of likely performance hit.
In JPA 1:
<property name="eclipselink.cache.shared.default" value="false"/>
and in JPA 2:
<shared-cache-mode>NONE</shared-cache-mode>
As an addition of shared cache, also EntityManager maintains cache. Single entity can refreshed from database via refresh method.

Categories

Resources