为什么我的代码不更新我的实体对象? Spring Hibernate MVC应用程序

时间:2011-10-26 17:40:12

标签: java hibernate spring jsp spring-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方法updatesaveOrUpdatemerge invoiceServiceHibernate.updateInvoice(invoice),但它不起作用。

控制器最终创建新发票而不是更新旧发票。有谁为什么会这样?我正在阅读this链接,它谈到了使用@ModelAttribute。我试过了,但它仍然无效。使用@ModelAttribute或@Valid什么都不做。该应用不会创建新发票,但不会更新当前发票。

有什么建议吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

您需要正在运行的交易。使用updateInvoice注释@Transactional

如果您没有设置,check here。简而言之,您需要在spring配置文件中使用<tx:annotation-driven />,并使用对会话/实体管理器的引用来声明事务管理器

答案 1 :(得分:2)

JSP中的ID在哪里?您似乎没有将invoice.id作为表单的一部分发回。

如果在传入请求中未以某种方式包含id,Hibernate无法确定应该更新哪个发票。 Spring的WebDataBinder的基本功能并不像看起来那么神奇。它所做的就是创建一个新对象(或者如果它存在于ModelMap中,则使用现有的对象),然后对bean设置器名称进行字符串匹配请求参数并调用setter。 (当然,类型转换会发生一些神奇的事情。)如果请求参数中没有ID,则当WebDataBinder创建新ID时,实体的ID字段将为空。您需要一种方法来为数据仓提供ID。

有两种基本方法可以实现这一目标。

首先,您可以绑定表单中Entity一部分的每个字段。你有invoice.id,invoice.version等隐藏字段。

其次,您可以在服务器的内存中保留实体的副本。这当然引入了服务器端状态,因此不完全是RESTful。您可以在控制器上使用Spring的@SessionAttributes来告诉它将实体保留在内存中,并让数据块使用新值更新它,而不是创建一个新值。