Why call session.flush () after session.delete () in Hibernate?

The problem is that the code fragment does not delete the record in the database.

import org.hibernate.Session; import org.hibernate.SessionFactory; ... ... void deleteForm() { Session session = sessionFactory.openSession(); FormDO formDO = new FormDO(); formDO.setId(formId); session.delete(formDO); // No delete SQL query is getting fired. 

However, if I call session.flush () after deletion, it works fine. Please note that I do NOT use transactions.

In the JavaDoc class of the Session class, the description of the delete method:

Remove the persistent instance from the data store. The argument may be an instance associated with the receiving session, or a temporary instance with an identifier associated with an existing persistent state.

And I saw a lot of code snippets on the Internet that shows that there is no need to call flush () after delete (). A similar question was raised in another forum here , but it remained unanswered.

In addition, session.save works fine without session.flush.

I am using Hibernate 4.2.16 + Spring 4.0.9 + JPA 1.0 annotations. Below are the source files for future reference.

FormDO.java

 import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="form") public class FormDO { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="id") Integer id; @Column(name="name") String name; ... ... 

Spring configuration file

  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/tempdb" /> <property name="username" value="root" /> <property name="password" value="****" /> </bean> <!-- Hibernate 4 SessionFactory Bean definition --> <bean id="hibernate4AnnotatedSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" > <property name="dataSource" ref="dataSource" /> <property name="annotatedClasses"> <list> <value>com.test.FormDO</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.current_session_context_class">thread</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> 

FormDAO.java

 @Named public class FormDAO { @Inject private SessionFactory sessionFactory; public boolean deleteForm(Integer formId) { Session session = sessionFactory.openSession(); FormDO formDO = new FormDO(); formDO.setId(formId); session.delete(formDO); session.flush(); // If this line is commented, record DOES NOT get deleted return true; } public boolean saveForm(FormDO formDO) { Session session = sessionFactory.openSession(); session.save(formDO); // Save doesn't require session.flush return true; } ... ... 

UPDATE:

My dilemma was largely due to inconsistency .. session.save inserted the record immediately, but session.delete does not reflect unless flush () was explicitly called. But when I link to the Flushing the Session link sent by Afsun, my doubts were cleared by reading the following line,

An exception is that objects using built-in authentication are inserted when they are saved.

I really appreciate the answers that everyone publishes, since almost all of them point in the right direction, but Afsun completely clears my doubts. Thanks!

+6
source share
3 answers

When you work with a database through Hibernate, you are using a Hibernate session . Hibernate sessions dumped into the database following three situations.

  • commit() - When you commit a transaction
  • Before running the request
  • When you call session.flush()

Here the most important thing is the second. After each request, there is no Hibernate session hidden database. If we run Native SQL Query through Hibernate, Hibernate does not know to clear the session, and also, if you start HQL , also Hibernate does not know to complete the session. A flash call synchronizes session state with the database.

See Next: Reset Hibernate Before Deleting and Clear Session

+5
source

From Javadoc for the Hibernate session class:

Flushing is the process of synchronizing the main stored storage with a stored state in memory.

When you make your call to session.delete() , you specify Hibernate to remove the entity from control. However, the corresponding record will still exist in the base database. You must make a session.flush() call to synchronize the database with the Hibernate session. Please note: if your program ended without your calling session.flush() , then the next time the application starts, the object in question will appear again.

+3
source

flush () This method causes the current session to be reset. Must be called at the end of the unit of work before making a transaction and closing the session (depending on the flash mode, Transaction.commit () calls this method). Flushing is the process of synchronizing a primary persistent storage with a stored state in memory.

Therefore, you must clear the session when you delete, otherwise the deleted record will still exist in the base database. Also, you do not close the sessions that you open. This can be a problem when you start using the join mechanism. Best practice is in most cases a session per request. Closing a session will always work in the database.
You also need to clear the batch processing, otherwise it may result in an OutOfMemoryException.

+1
source

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


All Articles