Entitymanager.flush() VS EntityManager.getTransaction().commit - What should I prefer?
JavaJpaEclipselinkJava Problem Overview
What should I prefer when updating the database? What are the pros & cons with either method and when shall I use the one or the other?
public void disemployEmployee(Integer employeeId, Date endDate) {
Employee employee = (Employee)em.find("Employee", employeeId);
employee.getPeriod().setEndDate(endDate);
em.flush();
}
public void disemployEmployee(Integer employeeId, Date endDate) {
Employee employee = (Employee)em.find("Employee", employeeId);
em.getTransaction().begin();
employee.getPeriod().setEndDate(endDate);
em.getTransaction().commit();
}
Java Solutions
Solution 1 - Java
In your first example, the changes to the data are reflected in database after encountering flush, but it is still in transaction.
But in second example, you are committing transaction immediately. Therefore the changes are made into the database & transaction also ends there.
Sometimes, flush may be useful to persist the data in between the ongoing transaction & then finally commit the changes afterwards. So you can also rollback the previous changes if there occurs some problem afterwards, like for batch insert/update.
Solution 2 - Java
You did read the javadoc for flush and commit and know that flush is only for use within a transaction? It flushes (but doesn't commit), whereas commit commits data (obviously). They are distinct; there is no "preference" to be had. The first example is wrong, and should result in an exception on calling flush (TransactionRequiredException)
Solution 3 - Java
Both of your code samples doesn't persist or merge the entity state to be written to DB.
I don't think it appropriate to compare EntityManager.flush()
and EnityManager.EntityTransaction.commit()
.
flush() MUST be enclosed in a transaction context and you don't have to do it explicitly unless needed (in rare cases), when EntityTransaction.commit() does that for you.
Refer this link https://stackoverflow.com/questions/949427/is-it-necessary-to-call-a-flush-jpa-interface-in-this-situation
Refer this link https://stackoverflow.com/questions/4415211/question-about-flushing-with-jpa-before-a-query-is-called for a scenario to use flush()
Solution 4 - Java
I would go for container managed transaction whenever possible. Bean managed transactions usually require significantly more code, because of the Exception possibilities. Also, it's more error prone (rollbacks, resource management).
That said, I would use a flush after the commit in container managed mode. That way I can catch possible PersistenceExceptions in my storage module and convert it to some more meaningful Exception for my use case module. This because I don't want to handle storage-specific Exceptions here, because I might swap the storage module out for something that does not use JPA... which never happened to me :)
Solution 5 - Java
I think the missing part is, flush() just add to the datasources to be ready to commit, gives actual ids but not persist by default.
So if you need flush() to work as commit() you need to set the flush mode to Commit in the EntityManager by:
void setFlushMode(FlushModeType flushMode)
Set the flush mode that applies to all objects contained in the persistence context.
Note that FlushModeType is an enum that has these two values:
> FlushModeType AUTO (Default) Flushing to occur at query execution. > Since: JPA 1.0 FlushModeType COMMIT Flushing to occur at transaction > commit. The provider may flush at other times, but is not required to. > Since: JPA 1.0
I hope this help