【问题标题】:Why doesn't model save my data after submitting a form?为什么模型在提交表单后不保存我的数据?
【发布时间】:2019-04-06 15:24:04
【问题描述】:

我的 Spring MVC 项目是一种事务服务,您可以在其中拥有客户和事务列表。我也在使用休眠。我有这个客户面板,客户可以在其中看到他的余额、以前的交易并能够进行新的交易。这是我的 .jsp 文件

的 sn-p

传输数据传递得很好,但“loggedClient”属性显示为一个空对象,nulls 作为值传递。这仅在单击 提交 按钮后发生,并且在刷新站点时不会发生。解决这个问题的关键可能是返回的 loggedClint.toString(): Client [id=0, firstName=null, lastName=null, email=null, balance=0] 任何想法为什么会发生这种情况?我该如何解决这个问题,所以在提交交易后,我的“loggedClient”属性仍然充满了客户的数据?

<div id="wrapper">
    <div id="header">
        <h2>Welcome ${loggedClient.firstName} ${loggedClient.lastName}</h2>

    </div>
    <header><label class="balancelabel" > Balance: ${loggedClient.balance} </label></header>
</div>
<br><br>
    <fieldset>
        <legend>Transfer Money</legend>
            <form:form action="transferMoney" modelAttribute="transferData" >
                <table>
                    <tbody>
                        <tr>
                            <td><label>Recipients Email:</label></td>
                            <td><form:input path="mail" /></td>
                        </tr>
                        <tr>
                            <td><label>Amount :</label></td>
                            <td><form:input path="amount" /></td>
                        </tr>
                        <tr>
                            <td><label></label></td>
                            <td><input type="submit" value="Send Transfer" class="save" /></td>
                        </tr>
                    </tbody>        
                </table>
            </form:form>
    </fieldset><div id="container">

    <div id="content">

        <table>

            <tr>
                <th>From</th>
                <th>To</th>
                <th>Amount</th>     
                <th>Timestamp</th>
                <!-- <th></th> -->
            </tr>

            <c:forEach var="tempTransfer" items="${transferList}">

                <tr>
                    <td>${tempTransfer.sender.lastName}</td>
                    <td>${tempTransfer.receiver.lastName}</td>
                    <td>${tempTransfer.amount}</td>
                    <td>${tempTransfer.timestamp}</td>


                </tr>

            </c:forEach>

        </table>

    </div>

这是控制器代码sn-p:

@PostMapping("/transferMoney")
public String processTransfer(@ModelAttribute("loggedClient") Client loggedClient, @ModelAttribute("transferData") TransferDataContainer transferData, Model model) {

    Client recipient = clientService.getClient(transferData.getMail());
    System.out.println(loggedClient.toString());
    if(transferData.getAmount() > loggedClient.getBalance()) {
        System.out.println("You cannot send more than you have");
        //System.out.println("You were trying to send : " + transferData.getAmount() +" but you have " +  loggedClient.getBalance());
    } else if(recipient==null) {
        System.out.println("Invalid recepient");
    } else {
        int amount = transferData.getAmount();
        // Updating data
        loggedClient.setBalance(loggedClient.getBalance()-amount);
        recipient.setBalance(recipient.getBalance()+amount);
        Transfer transfer = new Transfer(amount, new Timestamp(System.currentTimeMillis()) , loggedClient, recipient);

        clientService.saveClient(loggedClient);
        clientService.saveClient(recipient);
        transferService.saveTransfer(transfer);

    }
    return "client-logged";

}

【问题讨论】:

  • 您的代码没有改变loggedClient上的任何状态。它进入方法,您正在记录它。我们需要更多代码,或者您需要对您的接收者变量做一些事情。
  • @jasonArmstrong 我忘了在控制器方法的末尾添加,我正在返回调用该方法的相同 .jsp 文件。还有更多的代码来处理交易,但我选择不添加它(这就是... 的意思)。我最担心的是为什么loggedClient.toString() 给出的结果是:Client [id=0, firstName=null, lastName=null, email=null, balance=0] 似乎它使用了默认构造函数来创建一个新的Client 对象,而没有使用我已经保存在模型中的那个。
  • 您需要在问题中添加更多代码,以便我们了解您的操作方式;请张贴整个方法。在loggedClient 上,您没有描述任何正在发生变异的状态。如果你不改变状态或重新分配 arg,它就不会改变。
  • @JasonArmstrong 这是整个代码

标签: java html spring-mvc


【解决方案1】:

我相信我现在看到了问题所在。发生的事情是您的 JSP 中的 loggedClient 不在表单内,因此当提交表单时,只会发送 transferData 中的内容。如果您想将记录的客户端片段发回,您需要将其折叠为 transferData 中的隐藏输入字段。

例如,在您的 JSP 中:

<form...>
    <form:hidden path="loggedClient.firstName" value="${loggedClient.firstName"/> 
    <form:hidden path="loggedClient.lastName" value="${loggedClient.lastName"/>
...
</form>

然后在您的控制下,删除loggedClient 参数。更新您的 TransferData 类以包含一个 loggedClient 属性,您应该一切顺利。

【讨论】:

  • 我按照你的建议做了,但我遇到了一个奇怪的问题。我已将loggedClient 移至TransferData,它可以很好地显示客户名称、余额等。列表显示不好,所以我做了同样的事情:将 transferList 设置为 Transferdata 类的属性,并更新了 代码以包含 transferList。当我这样做时,我得到 http status 400 并由异常引起:_ java.lang.IllegalStateException:无法将类型“java.lang.String”的值转换为所需类型“com.janchabik.banking” .entity.Transfer 属性“transferList[0]”_
  • 听起来您正试图在传输中包含整个对象,而不仅仅是简单的数据。您不能在隐藏字段中包含复杂的数据/图表。听起来您可能正试图将过多的状态从客户端传输到服务器。我建议在这一点上阅读一些关于 Spring MVC 的教程,然后回到你当前的问题。
【解决方案2】:

发生这种情况是因为您的表单只有一个 modelAttribute。 当您提交表单时,仅传递一个对象,即 transferData。由于loggedClient 不是表单的一部分,您将永远得到另一个null。

无论如何,即使您尝试将loggedClient 作为表单输入参数传递,它也不会填充@ModelAttribute 客户端,因为表单已经有一个modelAttribute 表示“transferData”并且您不能在那里添加另一个。

如果你想传递记录的客户端信息,你必须改变方法。 我建议对记录的客户端使用会话,并且不要使用表单逐页传递它。

如果 session 不是你的解决方案,你必须使用 @ModelAttribute 你而不是必须考虑在 transferData 中添加loggedClient的字段并将它们添加到表单中作为输入参数(老实说设计很糟糕,所以我不建议这个)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 2012-08-24
    相关资源
    最近更新 更多