Announcement Announcement Module
Collapse
No announcement yet.
need help understanding delete within transaction issue Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • need help understanding delete within transaction issue

    I am using hibernate with spring. I use the TransactionInterceptor to wrap all my service methods within transactions. I use PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED as my transaction attributes.

    Everything has been working well, and this was surely simple to set up. However I have this one transaction where i am updating some data. I read in the new data and if the new data matches existing data, it deletes the existing data and then inserts the new data. It checks for the old data by a name field which has a unique constraint on it. I keep getting an error that the unique constraint is violated, this is because it is trying to insert the new data with the same name without deleting the old data.

    I have slowly debugged my app and it clearly calls the:
    getHibernateTemplate().delete(oldData)

    before it inserts the new data. The wierd thing is i have the hibernate debugging on so i can watch the console and the delete statements never appear. If i comment out the insert code and debug through i have noticed it will delete but the delete sql doesn't appear on the console until the transaction has been closed. However the insert statements appear right when they are called, hence my timing issue.

    Why do my selects, inserts, and updates all seem to be executed within the transaction right when they are called yet the delete statements don't execute until the end of the transaction?

  • #2
    Why do my selects, inserts, and updates all seem to be executed within the transaction right when they are called yet the delete statements don't execute until the end of the transaction?
    I think this is something internal to Hibernate - you might find out more on their forums. You can force HB to synchronize with the database through a flush (though AFAIK the hibernateTemplate does that internally) - however the changes should read the database only after the transaction has been committed.
    Try executing the delete/insert sequence inside a Callback and see what's your output.

    Comment


    • #3
      Inserts are executed immediately probably because you have an autoincrement key so Hibernate needs to execute the insert to fully create the object. All other sql statements are executed based on your flushing strategy.

      Solution would be to manually flush() whenever you need to make certain sql statements are executed in certain order.

      Comment


      • #4
        Originally posted by dejanp
        Inserts are executed immediately probably because you have an autoincrement key so Hibernate needs to execute the insert to fully create the object. All other sql statements are executed based on your flushing strategy.

        Solution would be to manually flush() whenever you need to make certain sql statements are executed in certain order.
        I am using an auto increment. That seems like a very inconsistent way for hibernate to do things.

        Comment


        • #5
          It's hard for me to tell if it's consistent or not - basically all ORM implementations (and that's including several EJB2 implementations) I used worked in a simmilar way, so I'm used to it. It's not really a problem once you know how it works.

          Comment


          • #6
            It's not inconsistent - it's the way it is suppose to work. Hibernate has to insert the object so it can assign a key to the object. Auto-increment is known to not be a perfect solution - there are other methods which should serve you just fine.

            Comment


            • #7
              well this is my first experience with an ORM so it seems kind of odd to me. If it has to call the insert within a transaction because of the auto-increment shouldn't it automatically flush?

              I mean it knows this may cause an error so why doesn't the orm step up and flush it for me?

              Comment


              • #8
                by the way thanks for the explanation at least i understand.

                To add on to my last comment. So if i am forced to flush to database because of the nature of my identity ids, what is the appropriate way to handle this. Should I insert a flush only when i see problems or should i just to be safe add a flush after every single delete call?

                I guess part of this question is, are there negatives to calling flush manually?

                Comment


                • #9
                  Well, if you need to flush manually in order to make it work, then I guess any negatives are irrelevant. Negative is basically the fact that your db records will be locked for a longer time and that it might happen that ORM needs to generates more then one statement for one record in one transaction. (This happens all the time anyways - the default Hibernate flushing strategy is to flush on commit and before queries, afaik)

                  The problems usually occur only if you use composite primary keys, unique indexes or simmilar complex db constrains. If the database schema you use is still in the design phase you may want to consider relaxing the db constraints. If your db schema is given and unchangeable or you don't want to change it then you are stuck with flushing I guess.

                  Comment


                  • #10
                    You might check if your DBMS supports deferring constraint checks until commit. Oracle can do this, for example.

                    Also, I assume there's some reason for doing a insert then a delete rather than an update.

                    Comment


                    • #11
                      Originally posted by dejanp
                      Well, if you need to flush manually in order to make it work, then I guess any negatives are irrelevant. Negative is basically the fact that your db records will be locked for a longer time and that it might happen that ORM needs to generates more then one statement for one record in one transaction. (This happens all the time anyways - the default Hibernate flushing strategy is to flush on commit and before queries, afaik)
                      And hibernate is doing this anyways because of the identies apparently. I guess if i wasn't using identity primary keys then this wouldn't be a problem but i don't see a good alternative.

                      Originally posted by dejanp
                      The problems usually occur only if you use composite primary keys, unique indexes or simmilar complex db constrains. If the database schema you use is still in the design phase you may want to consider relaxing the db constraints. If your db schema is given and unchangeable or you don't want to change it then you are stuck with flushing I guess.
                      I am thinking of two options to deal with this problem. One would be just to manually flushing delete's on tables that have one of these db constraints within the dao where it is called. In this way i could handle on an individual basis. The other would be to use aop to execute the deletes.

                      Personally i have come to the conclusion that this is a bug in hibernate. If it has to flush insert statements because of the identity primary keys it should naturally flush all the statements in the queue as well.

                      Comment


                      • #12
                        Originally posted by Loren Rosen
                        You might check if your DBMS supports deferring constraint checks until commit. Oracle can do this, for example.

                        Also, I assume there's some reason for doing a insert then a delete rather than an update.
                        Good thought however i am using hsqldb and i don't think this is an option.

                        Comment


                        • #13
                          Personally i have come to the conclusion that this is a bug in hibernate. If it has to flush insert statements because of the identity primary keys it should naturally flush all the statements in the queue as well.
                          I suggest to look for an answer on the hibernate forums - I'm pretty sure this problem should have poped up at some point.

                          Comment

                          Working...
                          X