为什么我的代码不更新我的实体对象? Spring Hibernate MVC 应用程序
我有一个 Spring Hibernate MVC 并尝试实现 CRUD 操作。我已经以“RESTful
”的方式创建、获取、删除,但我在更新时遇到困难。
当尝试更新对象时,参数是 /id?form,其控制器代码是:
@RequestMapping(value = "/{id}", params = "form", method = RequestMethod.GET)
public String updateForm(@PathVariable("id") Long id, Model uiModel) {
uiModel.addAttribute("invoice", invoiceServiceHibernate.getInvoice(id));
return "invoices/update";
}
因此,用于更新的 JSP 表单使用 id 填充对象。 JSP更新形式如下:
<c:if test="${!empty invoice}">
<form:form method="PUT" commandName="invoice">
<table>
<tr>
<td>Amount</td>
<td><form:input value="${invoice.amount}" path="amount" /></td>
</tr>
... more labels and fields ...
<tr>
<td colspan="3">
<input type="submit" value="Update Invoice" />
</td>
</tr>
</table>
</form:form>
提交后,被调用的控制器方法应该是:
@RequestMapping(method = RequestMethod.PUT)
public String update(Invoice invoice, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
if (bindingResult.hasErrors()) {
uiModel.addAttribute("invoice", invoice);
return "invoices/update";
}
uiModel.asMap().clear();
invoiceServiceHibernate.updateInvoice(invoice);
return "redirect:/invoices/";
}
我尝试过hibernate方法 update
、saveOrUpdate
和 merge< /code>
invoiceServiceHibernate.updateInvoice(invoice)
并且它不起作用。
控制器最终会创建一张新发票,而不是更新旧发票。有人知道为什么会这样吗?我正在阅读 此 链接,它讨论了使用@ModelAttribute。我已经尝试过了,但仍然不起作用。使用 @ModelAttribute 或 @Valid 没有任何作用。该应用程序不会创建新发票,但不会更新当前发票。
有什么建议吗?
谢谢!
I have a Spring Hibernate MVC and trying to implement CRUD
operations. I have gotten create, get, delete in a "RESTful
" kinda way but I am having difficulties with update.
When trying to update the object, the parameter is /id?form, the controller code for that is:
@RequestMapping(value = "/{id}", params = "form", method = RequestMethod.GET)
public String updateForm(@PathVariable("id") Long id, Model uiModel) {
uiModel.addAttribute("invoice", invoiceServiceHibernate.getInvoice(id));
return "invoices/update";
}
So, the JSP form for update gets filled with the object, using the id. The JSP update form is as follows:
<c:if test="${!empty invoice}">
<form:form method="PUT" commandName="invoice">
<table>
<tr>
<td>Amount</td>
<td><form:input value="${invoice.amount}" path="amount" /></td>
</tr>
... more labels and fields ...
<tr>
<td colspan="3">
<input type="submit" value="Update Invoice" />
</td>
</tr>
</table>
</form:form>
Upon submit, the controller method that gets called should be:
@RequestMapping(method = RequestMethod.PUT)
public String update(Invoice invoice, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
if (bindingResult.hasErrors()) {
uiModel.addAttribute("invoice", invoice);
return "invoices/update";
}
uiModel.asMap().clear();
invoiceServiceHibernate.updateInvoice(invoice);
return "redirect:/invoices/";
}
I have tried the hibernate method update
, saveOrUpdate
, and merge
invoiceServiceHibernate.updateInvoice(invoice)
and it does not work.
The controller ends up creating a new invoice instead of updating the old one. Does anyone why that is the case? I was reading up on this link and it talks about using @ModelAttribute. I've tried it but it still does not work. Using @ModelAttribute or @Valid does nothing. The app does not create a new invoice but it does not update the current invoice.
Any suggestions?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你的 JSP 中的 ID 在哪里?您似乎没有将发票.id 作为表单的一部分发回。
如果 id 未以某种方式包含在传入请求中,Hibernate 无法确定应更新哪个发票。 Spring的WebDataBinder的基本功能并不像看起来那么神奇。它所做的只是创建一个新对象(如果 ModelMap 中存在,则使用现有对象),然后将请求参数与 bean setter 名称进行字符串匹配并调用 setter。 (当然,类型转换等方面会发生一些神奇的事情。)如果请求参数中没有 ID,那么当 WebDataBinder 创建新的 ID 字段时,实体的 ID 字段将为空。您需要一种方法来向数据绑定器提供 ID。
有两种基本方法可以实现此目的。
首先,您可以绑定表单中实体的每个字段。您将有一个invoice.id、invoice.version 等的隐藏字段。
其次,您可以在服务器的内存中保留实体的副本。这当然引入了服务器端状态,因此并不完全是 RESTful。您可以在控制器上使用 Spring 的 @SessionAttributes 来告诉它将实体保留在内存中,并让数据绑定器使用新值更新它,而不是创建一个新值。
Where's the ID in your JSP? It looks like you're not sending back invoice.id as part of your form.
Hibernate doesn't have any way to figure out which invoice it's supposed to update if the id isn't included somehow in the incoming request. The basic function of Spring's WebDataBinder isn't really as magic as it seems. All it does is make a new object (or use an existing one if it exists in the ModelMap) then string-match request parameters against bean setter names and call the setters. (There is of course some magic happening for type conversion and so forth.) If there's no ID in the request parameters, the ID field of your Entity will be blank when the WebDataBinder makes a new one. You need a way to provide the ID to the databinder.
There are two basic ways you can accomplish this.
First you can bind every field that's part of the Entity in your form. You'd have a hidden field for invoice.id, invoice.version, etc etc.
Second you can keep a copy of the Entity around in memory on the server. This of course introduces server side state, so isn't exactly RESTful. You could use Spring's @SessionAttributes on your controller to tell it to keep the Entity in memory and have the databinder update it with the new values, instead of creating a new one.
您需要一个正在运行的事务。使用
@Transactional
注释updateInvoice
。如果您没有设置,查看此处。简而言之,您需要在 spring 配置文件中
,并声明一个引用会话/实体管理器的事务管理器You need a running transaction. Annotate
updateInvoice
with@Transactional
.If you don't have it set-up, check here. In short, you need
<tx:annotation-driven />
in your spring config file, and to declare a transaction manager with a reference to your session/entity manager