-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: Cant rollback transaction including HQL bulk delete on MySQL
PostPosted: Thu May 20, 2010 5:57 am 
Newbie

Joined: Wed Dec 16, 2009 6:10 am
Posts: 6
Location: Denmark
Setup:
Hibernate: hibernate-core-3.3.1.GA.jar
hibernate.cfg.xml:
Code:
        ...
        <property name="hibernate.connection.password">mypassword</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost/myschema</property>
        <property name="hibernate.current_session_context_class">thread</property>
        <property name="hibernate.connection.isolation">2</property>
        …

MySQL version: 5.1.34
MySQL JDBC driver: mysql-connector-java-5.1.7-bin.jar

Datamodel including entity B which extends from entity A (multi-table mapping).

We need to be able to delete a lot of A/B's (List<A> toBeDeleted) as fast as possible in one operation. We need to be able to roll back the transaction including the deletion.

We can do it like this:
Code:
    public void delete(List<A> toBeDeleted) {
        Iterator<A> it = toBeDeleted.iterator();
        while (it.hasNext())
        {
            session.delete(it.next());
        }
    }

But it is very slow when there is a lot A's in toBeDeleted, so we would like to bulk delete using HQL:
Code:
    public void delete(List<A> toBeDeleted) {
        List<Long> pids = new ArrayList<Long>(toBeDeleted.size());
        Iterator<A> it = toBeDeleted.iterator();
        while (it.hasNext())
        {
            pids.add(it.next().getPID());
        }
        Query query = session.createQuery("delete from A where pid in (:pids)");
        query.setParameterList("pids", pids);
        query.executeUpdate();
    }

Problem with this approach is that it uses a temporary table HT_A where it puts the pids of the A's to be deleted and then "delete from A where (pid) IN (select pid from HT_A)". This is fine but creating a temporary table in MySQL disables the possibility of rolling back the transaction (http://dev.mysql.com/doc/refman/5.0/en/ ... ommit.html), and that is a big problem for us.
We have tried to create our own hibernate dialect inheriting from org.hibernate.dialect.MySQL5InnoDBDialect. But we cant make that help us:
- We have tried to override performTemporaryTableDDLInIsolation to make it return Boolean.TRUE. But that results in "org.hibernate.exception.SQLGrammarException: could not insert/select ids for bulk delete"-exceptions caused by "com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'myschema.ht_a' doesn't exist"-exceptions.
- We have also tried to override supportsTemporaryTables to make it return false. But that results in "org.hibernate.HibernateException: cannot perform multi-table deletes using dialect not supporting temp tables"-exceptions.
So right now we need to do our deletion using SQL like this:
Code:
    public void delete(List<A> toBeDeleted) {
        List<Long> pids = new ArrayList<Long>(toBeDeleted.size());
        Iterator<A> it = toBeDeleted.iterator();
        while (it.hasNext())
        {
            pids.add(it.next().getPID());
        }
        SQLQuery query = session.createSQLQuery("delete from B where pid in (:pids)");
        query.setParameterList("pids", pids);
        query.executeUpdate();
        query = session.createSQLQuery("delete from A where pid in (:pids)");
        query.setParameterList("pids", pids);
        query.executeUpdate();
    }

But that is a little stupid because we would like to use as little SQL as possible, and because we need to maintain the code every time the subclass-hierarchy below A/B changes.

I think Hibernate-staff should make a solution to the problem so that you can bulk delete using HQL on MySQL and still be able to roll back the transaction including the deletion. It this the right place to make such a suggestion?


Top
 Profile  
 
 Post subject: Re: Cant rollback transaction including HQL bulk delete on MySQL
PostPosted: Tue May 25, 2010 12:28 pm 
Regular
Regular

Joined: Tue May 11, 2010 5:50 pm
Posts: 54
Location: Norman, Ok, U.S.A
try using a
for(all item){
Code:
     try{
          deletion code
      }catch(Exception e){
           rollback
      }
}


Top
 Profile  
 
 Post subject: Re: Cant rollback transaction including HQL bulk delete on MySQL
PostPosted: Tue May 25, 2010 12:44 pm 
Newbie

Joined: Wed Dec 16, 2009 6:10 am
Posts: 6
Location: Denmark
You didnt get the point. It is to slow deleting the items one by one (e.g. using "session.delete"). We need to delete them all in one (database) step. Therefore we need to use bulk-delete which have to be HQL or SQL.

ivirani wrote:
try using a
for(all item){
Code:
     try{
          deletion code
      }catch(Exception e){
           rollback
      }
}


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.