Announcement Announcement Module
Collapse
No announcement yet.
How to update entity partially Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to update entity partially

    Hi,

    I have an entity Userinfo having many fields. Some are with NotNull and some allows null value.

    Method Signature:

    @RequestMapping(value = "/userinfo/{id}/update", method = RequestMethod.POST)
    public String updateintercept(@Valid Userinfo userinfo, BindingResult result, ModelMap modelMap,HttpServletRequest request) {
    ...........
    }

    Entity: Userinfo
    Fields:

    userid(NotNull ),
    password(NotNull ),
    emailId(NotNull ),
    phone,
    enable(NotNull ),
    creattionDate(NotNull ),
    updationDate(NotNull )

    Now I want to update selected fields like email, phone, enable.
    I don't want to populate those fields into the form which are not getting updated.
    result.hasErrors() method returning true.

    Please suggest me the required changes in my code.

    Thanks & regards,
    Punit Kumar Dwivedi

  • #2
    I assume you dont want to update the creation date in this case,

    You can use JPA @Column(updatable = false)

    I have a similar setup which uses a BaseEntity with userWhoCreatedd/timeCreated , userWhomodified/Timemodified updated with Aspects,

    Comment


    • #3
      I have similar problem, but JPA with 'updatable' is not what I want. I have form that need to update only one field i.e. 'phone' (I don't want to populate in the page all fields like 'password', 'enable', ...).

      Comment


      • #4
        Hi entaroadun7,

        You should user following annotation for password, enable.
        @Column(updatable=false)

        Comment


        • #5
          Hi,

          I can't use 'updatable=false' because I have other forms where I allow to change password and enable.

          Comment


          • #6
            Well in that case you will need to have to write a custom form, controller and validator.

            You can probably reuse the form and controller with some if statements but the controller uses imlicit validator for your entity in ROO.

            Comment


            • #7
              I found I could keep the same form but just add render="false" to the field that I excluded.

              Then on the Controller I had to pull in the update method from the related ITD and use a test on the Spring Errors object to make sure only my excluded fields were there. Then I needed to find the object I want to update from the database (using the id from the backing bean) and copy the form fields from the backing bean to the object that I got from the database. Then I needed to persist the object I got from the database
              ... Is there any easier way?

              Comment


              • #8
                @SteveH1UK
                This solution would work, but it seems overkill in my opnion.

                Also if your controller should reject any value being put by the updating filed, in the case of render=false it would be null, but some one could manually add a field to the form (with tamper data) and submit it.

                You may also like to consider the transaction boundaries.

                So for example if host1 and host2 both try to change the password (in this example) host1 changes the password from "abc" to "xyz" and host2 does not change the password, but uses the older password to persist it back (I know bad passwords ..but this is just an example)

                lets see a trace

                host1 process feteches entity with password "abc"
                host2 also fetches same "abc"
                host1 updates password to "xyz" and persists entity
                host2 updates some thing other than password, and uses cached password in the controller "abc" and then persists.


                So in this very corner case you loose the update of "xyz" . host2 didn't want to update the password, but it did. And IMO this should be the guiding principle, if some thing is not intended to be updated, then don't. May be you can make the whole update transactional, the stock controller methods are not (AFAIK)

                I think updateable=false for cases like this, with a JDBC query to separately update the single field would work fine.

                I would appreciate any ideas on this regard as well.

                Comment


                • #9
                  re: Also if your controller should reject any value being put by the updating filed, in the case of render=false it would be null, but some one could manually add a field to the form (with tamper data) and submit it.

                  In the solution I outlined (getting object from database and copying the backing bean), I would only copy the updatable fields (i.e not the password)

                  I see your point about this breaking optimistic locking and that would require another bit of complexity that is better to be avoided - such as using the solution you suggest.

                  However, from the display point of view I can NOT get the solution I want to work. That is to use a read only field on the jspx to indicate to the user that this was a non-updatable field. On one form I wanted a non-updatable field (username) to be displayed and on the jspx I set the related field to disabled="true". However this failed validation in the controller that uses an @Valid annotation on the backing bean.

                  From my experiments (which I would love to be proved wrong) I found that you need to display all fields in your entity class in your jsp to prevent a failure in the @Valid annotation in the backing bean. To do anything else you must do some custom coding

                  Comment


                  • #10
                    >From my experiments (which I would love to be proved wrong) I found that you need to display all fields in your entity class in your jsp to prevent a failure in the @Valid annotation in the backing bean. To do anything else you must do some custom coding

                    have you tried disableFormBinding="true", you could actually pass a dummy value to the controller for readonly view when populating the view (pass it readonly createdTime and put it manually in a disabled input field, it should have no effect unless some one decides to rename the input box.

                    Comment


                    • #11
                      Sorry Hatim but this did not help me at all. I just had an empty field using
                      <code>
                      <field:input disabled="true" disableFormBinding="true" field="username" id="c_com_springsource_roo_pizzashop_domain_System User_username" required="true" z="user-managed"/>
                      </code>

                      Comment


                      • #12
                        but have you tried putting a dummy valid value in a hidden filed, you don't bind it spring way.

                        I think you can even do it in filed:input tag with value=""

                        This is assuming that you have updateable="false" and if some one tampers with hidden value, the worse that happens is form is not submitted.

                        With dummy valid value, the validation is passed, ofcourse this is messy, but not as messy as querying an entity and retrieving its values. Not only will it pass the validation, it will also retain the non updateable values.

                        Comment


                        • #13
                          I actually just tried it and works

                          <field:input field="password" id="c_com_hatimonline_code_roosec_domain_SystemUse r_password" render="false" z="tAD9z+w+wZw4Vu8Oz18Ku6M1PXY=" disableFormBinding="true" />
                          <input name="password" type="hidden" value="dummy"/>

                          As you can see the first one is not rendered at all, the second one is spitted out in HTML and not rendered, the trick is to use the correct name (note name is same as field)

                          Comment


                          • #14
                            I might give this a try tonight. In general I think this is an area that the Roo team could do with improving since for anything but a tiny project this is quite a common requirement.
                            Some initial comments:
                            1.) I do not like marking updatable attributes (e.g. password) as non-updatable in the domain class (although I suppose I could just about get over this with a well crafted comment - with the hope that the Roo team will give me a solution)
                            2.) For other non updatable fields such as creation date or username then you need to display the user the actual value both on initial display and when the form is re-displayed after a form validation failure

                            Comment


                            • #15
                              Did you try it with allowed/disallowed fields?

                              Have you tried an initBinder (see @InitBinder) in your controller where you can set allowed or disallowed fields, e.g. based on granted authorities of the user or any other condition. I had to set the @SessionAttributes annotation to get it to work with the default controllers created by Roo.

                              Since the form backing object has the original full object you can still display it as text or disabled form element (or don't show some elements based on sec:authorize rules to some application users).

                              Comment

                              Working...
                              X