Announcement Announcement Module
Collapse
No announcement yet.
SpringMVC/Hibernate/Validation Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • SpringMVC/Hibernate/Validation

    I am using Spring MVC with Spring Hibernate Transaction support set on my Manager classes which are set to blanket each method within my Manager classes (not using seperate ReadOnly type settings per method) and Spring Modules Commons Validator for validation.

    Assume JavaScript is turned off so the validation is done on the server side.
    It seems that when I do a form submission, my SimpleFormController retrieves my Command object, populates it with the form fields, then it does the validation. If it doesn't pass validation, it returns me to my form with the correct error messages just like it should.

    My question is this, at this point, I am using a Hibernate POJO as my Command object... it is dirty when it enters validation... the validator kicks out and Hibernate sees that my object is dirty and does an update... autocommit is on and from questions I've asked this is the way it should be... and the changes are committed because autocommit is true. At this point, my object is crap because it didn't pass validation but was updated anyway. Unfortunately, the Command object should indeed still have the incorrect data since it needs to go back to the form with whatever the user had entered regardless of whether it was invalid or not. This wouldn't be a big deal if I could force a user to correct the erros and move on... but as you'all know... that is not possible on a web app

    So... does this mean that using a Hibernate POJO as the form backing object with Spring MVC is a bad thing (I could have sworn that I got the idea from both Spring Live! and Spring in Action books)? or do you'all do something within the SimpleFormController that tells Hibernate not to do an update.

    The only thing I have come up with is to evict the object from the Hibernate session but I'm not sure where would be the best place to put this code.

    Any help would be appreciated.

    Thanks,
    Steve

  • #2
    Hi,

    You've stumbled on a common problem, and imho, it should be a FAQ and reflected in the documentation.

    In the meantime...

    I'm assuming you are using OpenSessionInView(Filter|Interceptor). If that's the case, you need to enable singleSession=false.

    Other options are to set readOnly = true for read only methods, but that only helps the situation (not entirely solves it), so you should use singleSession = false.

    This link will help to provide some background:

    http://forum.springframework.org/showthread.php?t=19109

    Let me know if you are using OSIV, we'll start with that.

    Seth

    Comment


    • #3
      I also ran into this problem and I simply do a brute force rollback if there are validation errors.

      Not very elegant, but works because the *only* thing in the transaction is the POJO. Any DB logging etc. happens in it's own transaction.

      Comment


      • #4
        sethladd,

        After you pointed me in the right direction, I skimmed through the org.springframework.orm.hibernate3.support.OpenSes sionInViewInterceptor api and also noticed that I had:

        Code:
        <property name="flushModeName" value="FLUSH_AUTO" />
        in my setup... so I looked to see what that does. Turns out that FLUSH_AUTO does a flush upon completion of any Transaction, hence, I believe the reason that setting singleSession=false works because you don't hit anymore transactions within your session. After reading about the cache not working if you set singleSession=false... I decided to try playing with flushMode.

        The way I read the API... it seems like you want flushMode to be NEVER if your using Transactions (which I am). So I set it to NEVER... however, I then found that I had to add new code to my saveAndUpdate methods which are as follows:

        Code:
         
        getSession().setFlushMode(FlushMode.AUTO);
        getHibernateTemplate().saveOrUpdate(user);
        getSession().flush();
        and my FlushMode is set to FLUSH_NEVER on my OSIV. I ended up having to put the manual flush even though it is set to AUTO... it's safe anyway.

        This seems to have fixed my problems... however, I haven't done thorough testing yet, so if anyone sees anything wrong with this approach... PLEASE let me know! It seems to me to be the best method that I've seen if I want to go the lazy route of using my Hibernate POJO's as my form backing objects

        Thanks,
        Steve

        Comment

        Working...
        X