Arhn - архитектура программирования

Почему мой код не обновляет мой объект сущности? Приложение 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 для обновления заполняется объектом с использованием идентификатора. Форма обновления 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/";
    }

Я пробовал метод гибернации update, saveOrUpdate и merge invoiceServiceHibernate.updateInvoice(invoice), и он не работает.

В конечном итоге контроллер создает новый счет вместо обновления старого. Кто-нибудь, почему это так? Я читал эта ссылка, и в ней говорится об использовании @ModelAttribute. Я пробовал это, но это все еще не работает. Использование @ModelAttribute или @Valid ничего не делает. Приложение не создает новый счет, но не обновляет текущий счет.

Какие-либо предложения?

Спасибо!


Ответы:


1

Где находится идентификатор в вашем JSP? Похоже, вы не отправляете invoice.id обратно как часть формы.

Hibernate не имеет никакого способа выяснить, какой счет он должен обновить, если идентификатор каким-либо образом не включен во входящий запрос. Основная функция Spring WebDataBinder на самом деле не такая волшебная, как кажется. Все, что он делает, это создает новый объект (или использует существующий, если он существует в ModelMap), затем сопоставляет строковые параметры запроса с именами установщиков компонентов и вызывает установщики. (Конечно, при преобразовании типов и т. д. происходит некоторое волшебство.) Если в параметрах запроса нет идентификатора, поле идентификатора вашей сущности будет пустым, когда WebDataBinder создаст новое. Вам нужен способ предоставить идентификатор для связывателя данных.

Есть два основных способа добиться этого.

Сначала вы можете связать каждое поле, являющееся частью Entity в вашей форме. У вас будет скрытое поле для invoice.id, invoice.version и т. д. и т. д.

Во-вторых, вы можете хранить копию Entity в памяти на сервере. Это, конечно, вводит состояние на стороне сервера, так что это не совсем RESTful. Вы можете использовать Spring @SessionAttributes на своем контроллере, чтобы сообщить ему, чтобы он сохранял Entity в памяти и чтобы связыватель данных обновлял его новыми значениями вместо создания нового.

26.10.2011
  • Ну, я просто думал, что это будет в состоянии понять это. Иногда при использовании фреймворка я никогда не знаю, когда и как что-то работает, это просто предполагается, но спасибо за ответ. Это правильно. 26.10.2011
  • Извините, не хотел быть таким бойким, писал в спешке. Отредактированный ответ, чтобы быть более полезным :) 27.10.2011
  • Спасибо за обновленный ответ. Комментарий @ SessionAttribute когда-нибудь пригодится 27.10.2011

  • 2

    Вам нужна работающая транзакция. Аннотировать updateInvoice с помощью @Transactional.

    Если вы не настроили его, проверьте здесь. Короче говоря, вам нужно <tx:annotation-driven /> в вашем файле конфигурации spring и объявить диспетчер транзакций со ссылкой на ваш диспетчер сеансов/сущностей.

    26.10.2011
  • Спасибо, и у меня есть это в классе InvoiceDAO. У меня есть @Transactional для создания, удаления и получения. 26.10.2011
  • а остальные настройки? Вы уверены, что транзакция выполняется? Поставьте точку останова и посмотрите, есть ли в трассировке TransacitonInterceptor. 26.10.2011
  • Я посмотрю на TransactionInterceptor. На самом деле у меня есть InvoiceDAO и еще один класс InvoiceService. @ Transactional находится в классе InvoiceService. Если я попытаюсь добавить @ Transactional в InvoiceDAO, это выдаст мне ошибки компонента. Метод updateInvoice InvoiceDAO вызывает sessionFactory.getCurrentSession().merge(invoice), а метод InvoiceService.updateInvoice вызывает InvoiceDAO.updateInvoice(invoice). 26.10.2011
  • Я ставлю точку останова в своем классе InvoiceServiceHibernate в разделе updateInvoice и запускаю сервер в режиме отладки. Метод вызывается, но идентификатор этого счета-фактуры равен нулю. Каким-то образом, когда я отправляю форму обновления в контроллер, идентификатор, который использовался для заполнения этой формы, исчез. Как мне это сделать? Поместите его в URL-адрес и используйте @ PathVariable = {id}? Спасибо 26.10.2011
  • ну да, у вас должно быть скрытое поле с id счета 26.10.2011
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..