从play framework表单调用JPA实体中的getter方法会调用setter函数

从play framework表单调用JPA实体中的getter方法会调用setter函数,jpa,playframework-2.0,Jpa,Playframework 2.0,我正在编写一个带有身份验证的简单play框架应用程序,其中密码使用BCrypt散列 简单地说,我的问题是:我观察到,在JPA实体中,当调用属性的get方法时,它的set方法也会被调用。如果我在set方法中执行非幂等运算,这就是一个问题 我将在这里描述我的问题的一个简化示例 这是我的登录视图 @helper.form(routes.Application.authenticate) { <h3>Login</h3> <ul id

我正在编写一个带有身份验证的简单play框架应用程序,其中密码使用BCrypt散列

简单地说,我的问题是:我观察到,在JPA实体中,当调用属性的get方法时,它的set方法也会被调用。如果我在set方法中执行非幂等运算,这就是一个问题

我将在这里描述我的问题的一个简化示例

这是我的登录视图

    @helper.form(routes.Application.authenticate) {
        <h3>Login</h3>
        <ul id="login_box">
            <li>
                <span class="loginbox_label">Username : </span>
                <input type="text" class="login_input" id="usernm-input" name="email" value='@form("email").value' placeholder="Enter Username..." />
            </li>
            <li>
                <span class="loginbox_label">Password : </span>
                <input type="password" class="login_input" id="passwd-input" name="password" placeholder="Enter Password..." />
            </li>
            <li>
            @if(form.hasGlobalErrors) { 
                <p class="error">
                    @form.globalError.message
                </p>
            }   
            </li>
        </ul>            
        <hr />
        <a href="#" onclick="javascript:window.location.href = '@routes.Application.forgotpwd()?usr='+$('#usernm-input').val()" class="forgotpwdlink">Retrieve Forgotten Password</a>
        <input type="submit" class="alt_btn login_btn" value="Login" />     
        <hr />
}
如您所见,我没有调用usr.setPassword方法。另外,我在else部分返回usr.getPassword(),以返回它并在页面上显示它,而不是错误消息

最后,这是我的用户类,一个JPA实体

@Transient
@Constraints.Required
@Formats.NonEmpty
private String password;

@Access(AccessType.PROPERTY)
@Column(name = "password")    
public String getPassword(){
    return this.password;
}

public void setPassword(String password){       
    this.password = password + "1";//BCrypt.hashpw(password, BCrypt.gensalt());
}
链接到完整的JPA实体:

我只是在这里添加了代码的相关部分。现在看看代码,您会发现每次提交表单时,它都必须返回存储的密码(因为我在else部分返回usr.getPassword()。注意this.password=password+1

现在,如果我继续提交错误的密码..这就是我得到的

很明显,每当我提交登录表单时,都会反复调用setPassword

为什么会这样


这是一篇很长的帖子,我知道您明确地为您的实体选择了属性访问。这意味着将调用setter来填充实体。但你的二传手并不是真正的二传手。因此,请将此方法重命名为其他方法,并添加一个真正的setter,或者使用字段访问而不是属性访问

    @helper.form(routes.Application.authenticate) {
        <h3>Login</h3>
        <ul id="login_box">
            <li>
                <span class="loginbox_label">Username : </span>
                <input type="text" class="login_input" id="usernm-input" name="email" value='@form("email").value' placeholder="Enter Username..." />
            </li>
            <li>
                <span class="loginbox_label">Password : </span>
                <input type="password" class="login_input" id="passwd-input" name="password" placeholder="Enter Password..." />
            </li>
            <li>
            @if(form.hasGlobalErrors) { 
                <p class="error">
                    @form.globalError.message
                </p>
            }   
            </li>
        </ul>            
        <hr />
        <a href="#" onclick="javascript:window.location.href = '@routes.Application.forgotpwd()?usr='+$('#usernm-input').val()" class="forgotpwdlink">Retrieve Forgotten Password</a>
        <input type="submit" class="alt_btn login_btn" value="Login" />     
        <hr />
}

IMHO,散列密码不应该由实体完成,更不应该由setter完成。预期的行为是getter应该返回setter设置的值。

屏幕截图中的“qwe123”是实际密码,但在每次调用身份验证时,都会通过缓慢更改数据库本身中的密码来调用该集..:(谢谢。我想我必须在业务逻辑层面上对此进行分析。
@Transient
@Constraints.Required
@Formats.NonEmpty
private String password;

@Access(AccessType.PROPERTY)
@Column(name = "password")    
public String getPassword(){
    return this.password;
}

public void setPassword(String password){       
    this.password = password + "1";//BCrypt.hashpw(password, BCrypt.gensalt());
}