Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate Delete query

Tags:

java

hibernate

When I try to delete an entry from a db, using

session.delete(object)  

then I can the following:

1) If the row is present in DB then two SQL queries are getting executed: A select and then a delete

2) If the row is not present in the DB then only the select query is getting executed

But again this is not the case for update. Irrespective of the presence of DB row, only the update query is getting executed.

Please let me know why this kind of behaviour for delete operation. Isn't it a performance issue since two queries are getting hit rather than one?

Edit:

I am using hibernate 3.2.5

Sample code:

SessionFactory sessionFactory = new Configuration().configure("student.cfg.xml").buildSessionFactory();     Session session = sessionFactory.openSession();     Student student = new Student();     student.setFirstName("AAA");     student.setLastName("BBB");     student.setCity("CCC");     student.setState("DDD");     student.setCountry("EEE");     student.setId("FFF");     session.delete(student);     session.flush();             session.close(); 

cfg.xml

<property name="hibernate.connection.username">system</property>     <property name="hibernate.connection.password">XXX</property>     <property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>     <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521/orcl</property>           <property name="hibernate.jdbc.batch_size">30</property>     <property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>     <property name="hibernate.cache.use_query_cache">false</property>     <property name="hibernate.cache.use_second_level_cache">false</property>     <property name="hibernate.connection.release_mode">after_transaction</property>     <property name="hibernate.connection.autocommit">true</property>     <property name="hibernate.connection.pool_size">0</property>     <property name="hibernate.current_session_context_class">thread</property>         <property name="hibernate.show_sql">true</property>     <property name="hibernate.hbm2ddl.auto">update</property>         

hbm.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.infy.model.Student" table="STUDENT">     <id name="id" column="ID">         <generator class="assigned"></generator>     </id>     <property name="firstName" type="string" column="FIRSTNAME"></property>     <property name="lastName" type="string" column="LASTNAME"></property>     <property name="city" type="string" column="CITY"></property>     <property name="state" type="string" column="STATE"></property>     <property name="country" type="string" column="COUNTRY"></property>         </class> 

like image 452
user182944 Avatar asked Nov 03 '12 15:11

user182944


People also ask

How do you delete a record in Hibernate query?

Try doing a session. flush() to flush the session, or a session. evict() to remove the object from the session.

How can I delete multiple rows in Hibernate?

In a non-transactional environment, multiple rows can be deleted in a batch in Hibernate something like the following. Session session=HibernateUtils. getSessionFactory(). getCurrentSession(); session.

What does the delete query do?

Using a specific criteria in a delete query Important: Use criteria to return only the records that you want to delete. Otherwise, the delete query removes every record in the table.

What is Session delete in Hibernate?

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.


2 Answers

The reason is that for deleting an object, Hibernate requires that the object is in persistent state. Thus, Hibernate first fetches the object (SELECT) and then removes it (DELETE).

Why Hibernate needs to fetch the object first? The reason is that Hibernate interceptors might be enabled (http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/events.html), and the object must be passed through these interceptors to complete its lifecycle. If rows are delete directly in the database, the interceptor won't run.

On the other hand, it's possible to delete entities in one single SQL DELETE statement using bulk operations:

Query q = session.createQuery("delete Entity where id = X"); q.executeUpdate(); 
like image 108
Diego Pino Avatar answered Oct 16 '22 13:10

Diego Pino


To understand this peculiar behavior of hibernate, it is important to understand a few hibernate concepts -

Hibernate Object States

Transient - An object is in transient status if it has been instantiated and is still not associated with a Hibernate session.

Persistent - A persistent instance has a representation in the database and an identifier value. It might just have been saved or loaded, however, it is by definition in the scope of a Session.

Detached - A detached instance is an object that has been persistent, but its Session has been closed.

http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/objectstate.html#objectstate-overview

Transaction Write-Behind

The next thing to understand is 'Transaction Write behind'. When objects attached to a hibernate session are modified they are not immediately propagated to the database. Hibernate does this for at least two different reasons.

  • To perform batch inserts and updates.
  • To propagate only the last change. If an object is updated more than once, it still fires only one update statement.

http://learningviacode.blogspot.com/2012/02/write-behind-technique-in-hibernate.html

First Level Cache

Hibernate has something called 'First Level Cache'. Whenever you pass an object to save(), update() or saveOrUpdate(), and whenever you retrieve an object using load(), get(), list(), iterate() or scroll(), that object is added to the internal cache of the Session. This is where it tracks changes to various objects.

Hibernate Intercepters and Object Lifecycle Listeners -

The Interceptor interface and listener callbacks from the session to the application, allow the application to inspect and/or manipulate properties of a persistent object before it is saved, updated, deleted or loaded. http://docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/listeners.html#d0e3069


This section Updated

Cascading

Hibernate allows applications to define cascade relationships between associations. For example, 'cascade-delete' from parent to child association will result in deletion of all children when a parent is deleted.

So, why are these important.

To be able to do transaction write-behind, to be able to track multiple changes to objects (object graphs) and to be able to execute lifecycle callbacks hibernate needs to know whether the object is transient/detached and it needs to have the object in it's first level cache before it makes any changes to the underlying object and associated relationships.

That's why hibernate (sometimes) issues a 'SELECT' statement to load the object (if it's not already loaded) in to it's first level cache before it makes changes to it.

Why does hibernate issue the 'SELECT' statement only sometimes?

Hibernate issues a 'SELECT' statement to determine what state the object is in. If the select statement returns an object, the object is in detached state and if it does not return an object, the object is in transient state.

Coming to your scenario -

Delete - The 'Delete' issued a SELECT statement because hibernate needs to know if the object exists in the database or not. If the object exists in the database, hibernate considers it as detached and then re-attches it to the session and processes delete lifecycle.

Update - Since you are explicitly calling 'Update' instead of 'SaveOrUpdate', hibernate blindly assumes that the object is in detached state, re-attaches the given object to the session first level cache and processes the update lifecycle. If it turns out that the object does not exist in the database contrary to hibernate's assumption, an exception is thrown when session flushes.

SaveOrUpdate - If you call 'SaveOrUpdate', hibernate has to determine the state of the object, so it uses a SELECT statement to determine if the object is in Transient/Detached state. If the object is in transient state, it processes the 'insert' lifecycle and if the object is in detached state, it processes the 'Update' lifecycle.

like image 38
Sashi Avatar answered Oct 16 '22 12:10

Sashi