24

Some confusing explanation: flush(); Flushing is the process of synchronizing the underlying persistent store with persistable state held in memory.it will update or insert into your tables in the running transaction, but it may not commit those changes.

If the changes are anyways going to be persisted in the database only after the commit then why to flush in the middle of the code.

And after running the flush if any changes are made to the managed object then will that throw an Exception or will those get synchronized and then will get perisisted. If they get synchronized then again why flush in the first place.

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Nick Div
  • 5,338
  • 12
  • 65
  • 127
  • Check this out, might answer: http://stackoverflow.com/questions/28392747/jpa-flush-vs-commit – Brad Peabody Aug 20 '15 at 02:28
  • @bgp Some of the answers say "flush is only for use within a transaction? It flushes (but doesn't commit), whereas commit commits data (obviously)" Thats my question whats the purpose of flush in all this. – Nick Div Aug 20 '15 at 02:43

2 Answers2

18

In theory, you (as a user of JPA) should never (or in absolutely rare situations) get in a situation to call flush().

Flushing is the process of synchronizing the underlying persistent store with persistable state held in memory

In other words, on a flush() all the insert, update, delete or whatever statements are actually called on the database, before a flush() nothing happens on your database. Flushing is caused by a commit of your transaction or some kinds of database reads. For example if you execute a JPQL query, a flush() has to be done to get the correct results from the database. But this is just very nice to know and completely handled by your JPA implementation.

There may be some situations you want to control this flushing on your own and then you can invoke it with flush().

Edit to answer the questions in comment:

Not on every read a flush is necessary, consider this scenario (one transaction):

  1. Read a person Person p = em.find(Person.class, 234)
  2. Update person p.setAge(31)
  3. Read a building Building b = em.find(Building.class, 123
  4. Read a building with JPQL query select b from Building b where b.id = 123

Automatic flush occurs only before 4., because Eclipselink can't determine what you are gonna read, so the person's age must be up to date on the database before this read can occur. Before 3. there is no flush needed because Eclipselink knows that the update on a person can not affect a building.

To work with optimistic locking, you have to implement it. Read about the @Version annotation here: https://blogs.oracle.com/carolmcdonald/entry/jpa_2_0_concurrency_and. Without that your entity will not use optimistic locking and the "last update wins".

Mathias Begert
  • 2,354
  • 1
  • 16
  • 26
  • So if I do a read on the database will the flush be called before the read automatically? – Nick Div Aug 20 '15 at 05:48
  • 1
    And one more small question, if one thread flushes some data on an entity and another thread makes some change to it and does a flush in its own transaction, is it going to throw an Optimistic Lock, I am just wondering because like you said flushed data is isolated to only the owing transaction, not visible to others. So can the other thread cause the optimistic lock? – Nick Div Aug 20 '15 at 06:22
  • I answered your questions in my answer above, but ask a new concrete question on SO rather than "extending" this one, it might not be helpful to others. – Mathias Begert Aug 20 '15 at 07:53
3

When the transaction commits the entity manager does that flush-ing for you. In some case, like handling optimistic locking in a container-managed transaction, you may need to manually invoke the flush method to catch and handle specific locking exception.

owenrb
  • 535
  • 2
  • 7
  • 2
    But when I do flush I dont see the data updated in the database. Some tutorials and some questions on SO mention that flush only moves data to a second level cache. I dont know what that means though but since the data is not in the database I dont know if it is that userful – Nick Div Aug 20 '15 at 02:46
  • As I remember, this is the same flush method used by the entity manager as well. If the update is not reflecting in the database there must be an exception being thrown during the commit process. It could be some unsychronized persistence context after the series of transaction events. – owenrb Aug 20 '15 at 03:04
  • 4
    @NickDiv A simple example: **persist** -> memory / **flush** -> database (isolated, not visible for others) / **commit** -> database (visible for others). Read about database transactions. – Mathias Begert Aug 20 '15 at 03:19
  • 1
    If you suspect it is a caching issue, you may try to disable caching via persistence.xml configuration file. Set the `shared-cache-mode` to `NONE` – owenrb Aug 20 '15 at 03:21
  • @OwenBringino Thanks so much for the answer. The cache does not seem to be the issue. And there is no exception being thrown as well. I dont know why I do not see the data in the DB. Is it possible that data flushed can be rolled back? – Nick Div Aug 20 '15 at 05:37
  • @MathiasBegert Thank you so much, your explanation makes a lot of sense. Simple and effective :-) I dont know why I do not see the data in the DB. Is it possible that data flushed can be rolled back? – Nick Div Aug 20 '15 at 05:39
  • @NickDiv did you try to check the data during the process using another db session? – Katrin Oct 12 '18 at 04:41