Подтвердить что ты не робот

Spring MVC - Выпадающий объект - Нет первичного идентификатора

Существует довольно распространенный случай использования, когда есть список объектов Java, из которых можно сделать выбор в веб-форме - обычно вы должны использовать первичный ключ объекта в качестве значения, чтобы контроллер мог либо делать поиск или просто привязать ключ к тому, какой объект создан/обновлен.

Моя проблема заключается в том, что список на выбор не является постоянным, ключевым объектам, они являются бизнес-моделями из службы, которые не имеют разумного способа получить их на основе содержащихся данных. Ниже приведен какой-то код psuedo, где список Foo указан на странице, и мы можем легко связаться с контроллером onSubmit имя Foo, но что, если есть другие поля Foo, которые необходимо отправить?

контроллер:

referenceData() {
    ...
    List foos = fooService.getFoosForBar( bar )
    return { 'foos', foos }
}

JSP:

<form>
   ...
<spring:bind path="formData.foo">
    <select name="<c:out value="${status.expression}" />">
        <c:forEach items="${foos}" var="foo">
            <option value="<c:out value="${foo.name}"/>">
                <c:out value="${foo.name}"/>
            </option>
        </c:forEach>
    </select>
</spring:bind>
   ...
</form>

Некоторые примеры решений заключались бы в использовании скрытых полей для отправки других свойств Foo и синхронизации их с изменением выбора, но я предпочитаю не использовать JavaScript в такой ситуации, где он, вероятно, добавит путаницу. Конечно, есть и другие способы сделать это.

Мой вопрос: существует ли какая-либо стандартная практика для этого? Или я должен просто придумать свой собственный способ сделать это? Я бы предпочел не изобретать колеса, если это возможно, и это настолько очевидно, что просто крыло может быть не лучшим.

4b9b3361

Ответ 1

Исходя из ваших ограничений, вы должны закодировать другие данные memobers foos как значение параметра.
<option label="${foo.name}" value="${foo.encodedValues}"/>
Метод encodedValues может выглядеть примерно так:


    private String SEPARATOR = ",";

    public String getEncodedValues()
    {
        final StringBuffer returnValue = new StringBuffer();

        returnValue.append(field1);
        returnValue.append(SEPARATOR);
        returnValue.append(field2);
        returnValue.append(SEPARATOR);
        returnValue.append(field3);

        return returnValue.toString();
    }

Если у вас есть выбор, который должен иметь закодированные значения, вы можете создать класс, который кодирует и декодирует эти значения, чтобы централизовать код.

Ответ 2

Вы можете использовать индекс элемента в списке, чтобы вернуть его в запрос POST.

<spring:bind path="formData.fooIndex">
  <select name="<c:out value="${status.expression}" />">
    <c:forEach items="${foos}" var="foo" varStatus="i">
        <option value="<c:out value="${i.index}"/>">
            <c:out value="${foo.name}"/>
        </option>
    </c:forEach>
  </select>
</spring:bind>

В вашем обработчике POST используйте foos.get(formData.getFooIndex()) Если foos может измениться между запросами GET и POST, вам нужно поместить foos в сеанс, чтобы вы определенно ссылались на один и тот же объект в обработчике POST, как и в обработчике GET.