LINUX.ORG.RU

Редактирование сущности через форму

 , ,


0

1

Есть сущность JPA:

@Entity
public class Video extends AbstractIdentifiable implements Serializable {

    @Column(nullable = true)
    @Temporal(value = TemporalType.TIMESTAMP)
    @JsonFormat(shape=JsonFormat.Shape.STRING, pattern=Format.DATETIME_FORMAT)
    private Calendar uploadDatetime;

    @ManyToOne
    @JsonIgnore
    @JoinColumn(nullable = false)
    private Member uploadMember;

    @Column(nullable = false)
    private String title;

    @Column(nullable = false)
    private String extension;

    @OneToMany(mappedBy = "video")
    @JsonIgnore
    private Set<VideoDisplay> videoDisplays = new HashSet<>();

    public Calendar getUploadDatetime() {
        return uploadDatetime;
    }

    public void setUploadDatetime(Calendar uploadDatetime) {
        this.uploadDatetime = uploadDatetime;
    }

    public Member getUploadMember() {
        return uploadMember;
    }

    public void setUploadMember(Member uploadMember) {
        this.uploadMember = uploadMember;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getExtension() {
        return extension;
    }

    public void setExtension(String extension) {
        this.extension = extension;
    }

    public Set<VideoDisplay> getVideoDisplays() {
        return videoDisplays;
    }

    public void setVideoDisplays(Set<VideoDisplay> videoDisplays) {
        this.videoDisplays = videoDisplays;
    }
}

Хочу через форму дать пользователю возможность редактировать title. Controller:

    @RequestMapping(value = "/{id}/edit", method = RequestMethod.GET)
    public String edit(@PathVariable(name = "id") Long id, Model model) {
        if (!model.containsAttribute("video")) {
            Video video = dataService.get(Video.class, id);
            if (video == null) {
                //TODO: отобразить сообщение
                return "redirect:/admin/videos";
            } else {
                model.addAttribute("video", video);
            }
        }
        return "admin/videos/edit";
    }

    @RequestMapping(value = "/{id}/edit", method = RequestMethod.POST)
    public String editPerform(@PathVariable(name = "id") Long id, @Valid Video video, BindingResult bindingResult, Model model) {
        if (bindingResult.hasErrors()) {
            return edit(id, model);
        }
        dataService.merge(video);
        return ("redirect:/admin/videos");
    }

Template:

<div class="card-body" th:fragment="form_edit">
        <form class="needs-validation" novalidate method="post" th:action="@{${#httpServletRequest.requestURI}}" th:object="${video}">
            <div class="form-row">
                <div class="col-md-4 mb-3">
                    <label for="title" th:text="#{title}"/>
                    <input type="text" class="form-control" th:attrappend="class=${#fields.hasErrors('title') ? ' is-invalid' : ''}" id="title" th:placeholder="#{title}" th:field="*{title}" required/>
                    <div class="invalid-feedback" th:if="${#fields.hasErrors('title')}">
                        <p th:each="error: ${#fields.errors('title')}" th:text="${error}"/>
                    </div>
                </div>
                <div class="col-md-4 mb-3">
                    <label for="extension" th:text="#{extension}"/>
                    <input readonly type="text" class="form-control" th:attrappend="class=${#fields.hasErrors('extension') ? ' is-invalid' : ''}" id="extension" th:placeholder="#{extension}" th:field="*{extension}" required/>
                    <div class="invalid-feedback" th:if="${#fields.hasErrors('extension')}">
                        <p th:each="error: ${#fields.errors('extension')}" th:text="${error}"/>
                    </div>
                </div>
            </div>
            <button class="btn btn-primary" type="submit" th:text="#{submit}"/>
        </form>
    </div>

В итоге в editPerform приходит сущность c заполненными только title и extension и как следствие выполняется update с null колонками:

update Video set extension=?, title=?, uploadDatetime=?, uploadMember_id=? where id=?
Есть ли способ обновлять только те поля, которые заданы в форме? Или заполнять объект сущностью из базы, устанавливать ему значения из объект пришедшего из формы и затем уже сохранять его?


Или заполнять объект сущностью из базы, устанавливать ему значения из объект пришедшего из формы и затем уже сохранять его?

Угу. В общем случае тебе в контроллер прилетает id объекта и поля которые надо изменить, ты по id вытаскиваешь сущность (он как правило уже будет в кеше jpa), и изменяешь нужные поля. Руками, да-да, потому что эта вся архитектура рассчитана на изменение всех полей. Хотя это можно автоматизировать через reflection.

Но учти, что у тебя будет нюанс, когда надо поле установить в null, для этого надо отличать случаи когда значение поля не указано совсем, и когда указано, но null.

Deleted
()

Или заполнять объект сущностью из базы, устанавливать ему значения из объект пришедшего из формы и затем уже сохранять его?

Да. Если тебе будет от этого проще жить, при правильно настроенном ORM кешировании недавно вытащенный из базы объект будет лежать в кеше и запрос к базе скорее всего делаться не будет.

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 2)
Ответ на: комментарий от Legioner

Да. Если тебе будет от этого проще жить, при правильно настроенном ORM кешировании недавно вытащенный из базы объект будет лежать в кеше и запрос к базе скорее всего делаться не будет.

Это был бы идеальный вариант, если все происходило бы автоматически. Делать это вручную попахивает каким-то говнокодом =)

totik
() автор топика
Ответ на: комментарий от totik

В жаве принято писать много тривиального кода. Если не хочется, можно навелосипедить волшебную магию на рефлекшне. Я бы не советовал, но тут на любителя.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

В жаве принято писать много тривиального кода.

Кем принято? Спринг наоборот пытается минимизировать это, тоже проект «Spring Data REST» тому пример. То что всё это превращается в «закат солнц ручную», как только захочется сделать шаг в сторону, ну так это нюансы 8)

Deleted
()
Ответ на: комментарий от Deleted

К сожалению, я уже давно не пользовался Spring MVC.

Намного проще редактировать сущность при помощи

http://examples.sencha.com/gxt/4.0.3/

Надо просто создать «переходник» (адаптер) типа Имя_классаProperties для полей сущности JPA и с GWT.create(Имя_классаProperties.class) использовать полученные данные в таблицах, деревьях, списках и т.п..

Я не навязываю своё решение, но попробовать можно.

Bioreactor ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.