Announcement Announcement Module
Collapse
No announcement yet.
session.flush() really needed after session.delete()? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • session.flush() really needed after session.delete()?

    I was tinkering with a DAO pattern using HibernateDaoSupport recently, but found that if i didn't explicitly call flush() after a delete() call in the DAO layer, the delete query for the persisted object would never be passed to the database?

    Am I missing something here? I was under the impression that HibernateDaoSupprt was supposed to wrap my HibernateCallback instances in the standard session lifecycle logic?

    Ryan

  • #2
    Ryan, Could you please provide more details about your issue?
    Are you wrapping your DAO calls in transcation?
    Could you please show an excerpt of your applicationContext?
    I have been using HibernateDaoSupport / HibernateTemplate since a long time and found it very stable/helpfull.

    Comment


    • #3
      Here is my applicationContext.xml. I am currently not implementing a transaction proxy as the backend is mysql, and it seems unneccesary to use tx's with a MyISAM DB.

      Code:
      <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
      <beans>
      	<bean id="myDataSource" 
      		class="org.springframework.jndi.JndiObjectFactoryBean">
      		<property name="jndiName">
      			<value>java&#58;comp/env/jdbc/wwbc</value>
      		</property>
      	</bean>
      	<bean id="sessionFactory" 
      		class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
      		<property name="mappingResources">
      			<list>
      				<value>org/wwbc/dao/mappings/Headlines.hbm</value>
      				<value>org/wwbc/dao/mappings/News.hbm</value>
      				<value>org/wwbc/dao/mappings/Users.hbm</value>
      			</list>
      		</property>
      		<property name="hibernateProperties">
      			<props>
      				<prop key="hibernate.dialect">
      					net.sf.hibernate.dialect.MySQLDialect</prop>
      				<prop key="show_sql">true</prop>
      			</props>
      		</property>
      		<property name="dataSource">
      			<ref bean="myDataSource"/>
      		</property>
      	</bean>
      	<bean id="org.wwbc.dao.services.NEWS_SERVICE" 
      		class="org.wwbc.dao.hibernate.NewsDAOImpl">
      		<property name="sessionFactory">
      			<ref bean="sessionFactory" />
      		</property>
      	</bean>
      	<bean id="org.wwbc.dao.services.USERS_SERVICE" 
      		class="org.wwbc.dao.hibernate.UsersDAOImpl">
      		<property name="sessionFactory">
      			<ref bean="sessionFactory" />
      		</property>
      	</bean>
      Here is my method implementation in my DAO for deletion of the object.

      Code:
      public class NewsDAOImpl extends HibernateDaoSupport implements INewsDAO &#123;
      	public void deleteNews&#40;final News news&#41; throws DAOException &#123;
      		HibernateCallback callback = new HibernateCallback&#40;&#41; &#123;
      			public Object doInHibernate&#40;Session session&#41;
      					throws HibernateException, SQLException &#123;
      				session.delete&#40;news&#41;;
      				session.flush&#40;&#41;;
      				return null;
      			&#125;
      		&#125;;
      		
      		try &#123;
      			callback.doInHibernate&#40;getSession&#40;&#41;&#41;;
      		&#125; catch &#40;Exception e&#41; &#123;
      			throw new DAOException&#40;"Could not delete news article. &#40;News ID&#58; " + news.getId&#40;&#41; + "&#41;", e&#41;;
      		&#125;
      	&#125;
      &#125;
      I really didn't think i'd have to use the flush() method on my own - my understanding was that HibernateDaoSupport handled this for me (as I said in my original post). using flush() works though, but it would be nice to know if this is truly neccesary or if something else is horribly wrong.

      Thanks,

      Ryan

      Comment


      • #4
        Ryan,
        Your applicationContext looks great but it lacks the transaction management.

        Could you please do the following:
        1. add these declarations to your applicationContext:
        Code:
          <!-- Hibernate Transaction Manager -->
          <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
            <property name="sessionFactory"><ref local="sessionFactory"/></property>
          </bean>
        
          <!-- Transaction Proxy Template -->
          <bean id="txProxyTemplate" lazy-init="true"
                class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <property name="transactionManager"><ref local="transactionManager"/></property>
            <property name="transactionAttributes">
              <props>
                <prop key="*">PROPAGATION_REQUIRED</prop>
              </props>
            </property>
          </bean>
        2. redefine your DAO:
        Code:
          <bean id="org.wwbc.dao.services.NEWS_SERVICE"        parent="txProxyTemplate">
            <property name="target">
              <bean class="org.wwbc.dao.hibernate.NewsDAOImpl"> 
                <property name="sessionFactory"> 
                   <ref bean="sessionFactory" /> 
                </property> 
              </bean>
            </property>
           </bean> 
        
          <bean id="org.wwbc.dao.services.NEWS_SERVICE"        parent="txProxyTemplate">
            <property name="target">
               <bean id="org.wwbc.dao.services.USERS_SERVICE" 
              class="org.wwbc.dao.hibernate.UsersDAOImpl"> 
              <property name="sessionFactory"> 
                 <ref bean="sessionFactory" /> 
              </property> 
              </bean>
            </property>
           </bean>
        3. remove calls to flush() from your DAOs

        For more informations, please review the jpetstore sample. You could too read Colin Sampaleanu weblog

        Comment


        • #5
          Will do. I was not aware that transaction management was neccesary even in cases where a non-transactional database is in use. I've use the JTA proxies in other instances where I've had transaction-managed backends like Sybase and Oracle, but wasn't aware it was required here.

          Appreciate your help, cheers.

          Ryan

          Comment


          • #6
            One last thing!!!
            I googled "spring hibernate transaction mysql isam" and found the following weblog entry.
            I neved tried Spring Framework + Hibernate + MySQL (ISAM). I think it is time to do.

            Comment


            • #7
              Delete not working inside a transaction

              Hi,
              I'm using hibernate3 and Spring 2.0 aop based declarative Txn to carry out a transaction. It seems weird that unless I call session.flush() explicitly a session.delete(object) call is not executed before save(). I'm using PROPAGATION required everywhere and the transaction works as expected if I remove the delete call. Save() inserts a unique key for an object that's supposed to be deleted by delete call. As a result, it throws ConstraintVIolation error.
              It may be a hibernate issue as I'm injecting hibernate3transactionmanager.

              Even when I tried the following code with raw hibernate transaction, it didn't call the delete(Object) before save(). But instead if I deleted an object thru HQL it became the part of transaction.

              try {
              HibernateUtil.beginTransaction();
              Card c = getCard(serialNumber);

              if(c!=null) {
              delete(c);
              //HibernateUtil.getSession().flush();
              }
              Card card = new Card();
              //..setters called
              save(card);
              HibernateUtil.commitTransaction();
              }catch(Exception e) {
              e.printStackTrace();
              HibernateUtil.rollbackTransaction();
              }

              A glance at http://www.hibernate.org/hib_docs/re...jectstate.html section 10.10 tells that entity deletes are called after entity saves. If that's true then txn management is an issue.

              Please let me know if I'm missing something.

              Comment


              • #8
                It has nothing to do with transactions, it's simply the order of generating the sql statements that doesn't work for your case. If you could change the order so that it works for your case, it would break somewhere else.

                You can try to control the ordering of sql statement generation by using flush, you can try to relax your db constraints or you can use jdbc.

                Comment


                • #9
                  Thanks Dejanp for the reply.
                  What you're suggesting is understandable from the hibernate docs.
                  Changing the order would mean a compromise which I can do even with an update instead of delete/insert.
                  And i don't think even changing the txn mgr implementation to openJTA can help here. But my real concern is actually the order of the DMLs and am looking if spring(?) or hibernate has a work-around. They should be executed in the order they were sent and flush should do the same thing so that the transactional sanctity is maintained.

                  Comment


                  • #10
                    Statements can't be executed in the order of "sending" because most of update statements are never "sent" but generated implictly as a result of entities getting dirty. If you are talking only about explicit stuff you can try to set flushMode to "always".

                    Anyway - you can try to take this to Hibernate forums, but I don't think you will get any kind of response on this from Hibernate people, as they made it this way on purpose. Spring can't help you either because it's internal Hibernate stuff.

                    Comment

                    Working...
                    X