当没有任何改变时,Spring实体正在被修改

时间:2015-01-24 23:24:03

标签: java spring spring-mvc spring-roo

我正在使用Spring Roo创建一个带有用户管理的简单Web应用程序。我有一个AppUser实体,其中包含password字段,当更新实体的其他属性时,即使我没有更改它,也会将其设置为null。

为了实现更新AppUser实例的用例,Roo生成了两种方法updateFormupdate

前一种方法准备用于编辑实体的表单:

@RequestMapping(value = "/{id}", params = "form", produces = "text/html")
public String updateForm(@PathVariable("id") Long id, Model uiModel) {
    AppUser appUser = AppUser.findAppUser(id);
    populateEditForm(uiModel, appUser);
    System.out.println("On Update Form - " + appUser);
    return "users/update";
}

第二种方法检查验证错误并将实体合并到JPA上下文中:

@RequestMapping(method = RequestMethod.PUT, produces = "text/html")
public String update(@Valid AppUser appUser, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
    System.out.println("On Update - " + appUser);
    if (bindingResult.hasErrors()) {
        populateEditForm(uiModel, appUser);
        return "users/update";
    }
    uiModel.asMap().clear();
    appUser.merge();
    return "redirect:/users/" + encodeUrlPathSegment(appUser.getId().toString(), httpServletRequest);
}

编辑表单中password字段的默认值为空,但是在它的mutator方法setPassword上,当发送null或空白时,我没有更新密码。

public void setPassword(String password) {
    // Don't update password if null or blank is sent
    if (password != null && !password.isEmpty()) {
        String encodedPassword = passwordEncoder.encodePassword(password, null);
        this.password = encodedPassword;
    }
}

标准输出的结果如下:

On Update Form - AppUser[username=user,password=04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb,enabled=true,appRole=AppRole[rolename=ROLE_USER,id=2,version=1],customer=Customer[code=<null>,description=default,address=<null>,cap=<null>,locality=<null>,province=<null>,telephone=<null>,fax=<null>,vat=<null>,fiscalCode=<null>,sex=<null>,customerType=<null>,insertionDate=<null>,lastVisit=<null>,id=0,version=<null>],id=2,version=0]

On Update - AppUser[username=user,password=<null>,enabled=true,appRole=AppRole[rolename=ROLE_USER,id=2,version=1],customer=Customer[code=<null>,description=default,address=<null>,cap=<null>,locality=<null>,province=<null>,telephone=<null>,fax=<null>,vat=<null>,fiscalCode=<null>,sex=<null>,customerType=<null>,insertionDate=<null>,lastVisit=<null>,id=0,version=<null>],id=2,version=0]

显然密码正在改变,但我无法理解在哪里。

修改

我用来更新AppUser信息的jspx视图如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:field="urn:jsptagdir:/WEB-INF/tags/form/fields" xmlns:form="urn:jsptagdir:/WEB-INF/tags/form" xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <jsp:output omit-xml-declaration="yes"/>
    <form:update id="fu_it_digitelematica_leovince_domain_AppUser" modelAttribute="appUser" path="/users" versionField="Version" z="9/aOTZ+wTF1ijLMgiWkx1JcbpG8=">
        <field:input field="username" id="c_it_digitelematica_leovince_domain_AppUser_username" required="true" z="H3JOKuXes6/RLOnAd4x1v0j3Njo="/>
        <field:input field="password" id="c_it_digitelematica_leovince_domain_AppUser_password" required="false" type="password" z="user-managed"/>
        <field:checkbox field="enabled" id="c_it_digitelematica_leovince_domain_AppUser_enabled" z="4WIlYpFXs46FLp4l8koJ2DXmWz8="/>
        <field:select field="appRole" id="c_it_digitelematica_leovince_domain_AppUser_appRole" itemValue="id" items="${approles}" path="/approles" required="true" z="KDeZRlxip/VWLtb/kN58hn2zZdg="/>
        <field:select field="customer" id="c_it_digitelematica_leovince_domain_AppUser_customer" itemValue="id" items="${customers}" path="/customers" required="true" z="rEMR1CzjRLuSkoIKTHmq4N+qZoI="/>
    </form:update>
</div>

2 个答案:

答案 0 :(得分:0)

您是否尝试删除&#34; type = password&#34;来自你的领域的属性:输入?

也许,input.tagx上有一个错误......你能试试吗?

如果您检测到错误,则可以在http://jira.spring.io/browse/ROO

上创建问题

答案 1 :(得分:0)

这是标准方式:合并实体时,覆盖其所有值。让我解释一下:

  1. RequestHandler创建一个新的用户实例,并用请求值
  2. 填充它
  3. 实例附加到 entityManager ,并将其存储在数据库中。
  4. 在第2点 entityManager 对提交及其值不了解,因此,当您合并用户时,如果password字段为null,则该字段将为DB上的字段的新值。这就是为什么Spring Roo生成的视图包含更新形式的所有字段。

    要解决此问题,您必须加载附加的实体实例,并填写绑定实例的缺失值(警告,未测试代码 ):

    @RequestMapping(method = RequestMethod.PUT, produces = "text/html")
    public String update(@Valid AppUser appUser, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
        System.out.println("On Update - " + appUser);
        if (bindingResult.hasErrors()) {
            populateEditForm(uiModel, appUser);
            return "users/update";
        }
        uiModel.asMap().clear();
        User attached = User.findUserById(user.getId());
        appUser.setPassword_encoded(attached..getPassword());
        appUser.merge();
        return "redirect:/users/" + encodeUrlPathSegment(appUser.getId().toString(), httpServletRequest);
    }
    

    你需要一个设置密码而不编码的mutator。

    祝你好运!