Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it necessary to call session.flush() after session.delete() in Hibernate?

The problem is following code snippet doesn't delete the record in DB.

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 delete, it works perfectly. Please note, I am NOT using any Transaction.

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

Remove a persistent instance from the datastore. The argument may be an instance associated with the receiving Session or a transient instance with an identifier associated with existing persistent state.

And I have seen many code snippets online which shows that it is not necessary to call flush() after delete(). Similar question was raised in other forum here but it remained unanswered.

Also, session.save works fine without session.flush.

I am using Hibernate 4.2.16 + Spring 4.0.9 + JPA 1.0 annotations. Following are the source files for further 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 the inconsistency.. session.save was inserting the record immediately but session.delete doesn't reflect unless flush() was called explicitly. But when I refer the Flushing the Session link posted by Afsun, my doubts were cleared by reading following line,

An exception is that objects using native ID generation are inserted when they are saved.

I really appreciate the answers posted by everyone as almost all of them were pointing to the right direction but Afsun clears my doubt totally. Thanks!

like image 238
Gaurang Patel Avatar asked May 13 '15 12:05

Gaurang Patel


1 Answers

When your work with database via Hibernate you are using Hibernate session. Hibernate sessions flushed to the database by following three situations.

  1. commit()- When you commit a transaction
  2. Before you run a query
  3. When you call session.flush()

Here the most important is second. After every query does not Hibernate session flush database. If we run Native SQL Query via Hibernate,Hibernate does not know to flush the session or also if run HQL also Hibernate does not know to flush session. The call to flush will synchronise the session state with the database.

See the following: Hibernate flush before delete and Flushing the Session

like image 125
Afsun Khammadli Avatar answered Oct 06 '22 00:10

Afsun Khammadli