Hi,
I'm Thorben Janssen from thoughts-on-java.org with a new Hibernate Tip.
This time I will show you how to detach entities from your persistence context.
As I explained in one of my previous video
and in my Hibernate Performance Tuning training:
When you need to update or delete a huge number of entities,
it is often better to use a JPQL
or SQL statement
instead of updating one entity after the other.
Instead of performing at least one query for each updated entity
you then just need to execute 1 query.
But the JPQL or SQL statement also has a disadvantage.
Hibernate doesn't know which database records you're updating
and can't replicate the changes
to the entities stored in the persistence context
or 1st level cache.
You, therefore, need to do that yourself and detach all entities
from the persistence context
before you execute the query.
That's when I always get the same question:
How do you detach an entity from the persistence context?
You can do that in two steps:
First, Make sure that Hibernate persisted all pending changes in the database
And second, remove the entities from the persistence context
Step 1 is crucial because Hibernate delays the execution of all write operations
as long as possible.
Your persistence context
might contain new entities which were not inserted into the database
or dirty entities that require the execution of an SQL update statement.
When you detach these entities from the persistence context,
Hibernate will not perform the required SQL statements,
and you will lose these pending changes.
You can prevent that by calling the flush method
on the EntityManager.
After you've done that,
you can remove a specific entity from the persistence context
by calling the detach method
or you can call the clear method to clear the persistence context completely.
I prepared a simple example.
I first load the Book entity with id 1 from the database
and write it to the log file.
Then I change the title attribute.
The entity is now dirty,
and Hibernate will generate an SQL UPDATE statement for it
when it flushes the persistence context.
In the next step,
I trigger the flush
by calling the flush method on the EntityManager.
Hibernate now performs a dirty check on all managed entities
and executes the required SQL statements
to write all pending changes to the database.
Now I can call the clear method
to detach all entities
without losing any pending changes.
After this is done,
I can execute a JPQL UPDATE query
and change the price of all entities.
When I now call the EntityManager find method,
Hibernate has to execute an SQL query
because the Book entity is no longer managed by the persistence context.
The Database returns the updated record,
and this log statement
will write the entity
with the updated title
and price to the log file.
Here you can see the log messages.
Hibernate performs an SQL SELECT statement
to get the Book entity with id 1
before I write it to the log file.
This update statement was triggered by the
change of the title attribute
and the call of the flush method.
The changed title is now stored in the database.
Hibernate then performs the JPQL UPDATE statement
to update the price and another SQL SELECT statement
to retrieve the Book entity with id 1.
As you can see here,
the title and the price are now updated.
OK, that's it for today.
If you want to learn more about Hibernate,
you should join the free Thoughts on Java Library.
It gives you free access to a lot of member-only content
like an ebook about the Java 8 support in Hibernate,
a printable PDF version of this Hibernate Tip,
lots of cheat sheets and a video course.
I'll add the link to it to the video description below.
See you next week for a new Hibernate Tip
and if you like today's video,
please give it thumbs up and subscribe below.
Bye
Không có nhận xét nào:
Đăng nhận xét