使用 Thymeleaf 为嵌套对象创建表单的问题

Posted

技术标签:

【中文标题】使用 Thymeleaf 为嵌套对象创建表单的问题【英文标题】:Problem with Creating a form for a nested object with Thymeleaf 【发布时间】:2019-10-06 03:59:22 【问题描述】:

我正在使用 Spring Boot 2Thymeleaf 创建一个 MVC 应用程序。

我在为复杂对象创建表单时遇到了一些麻烦。我得到了我的类 MedicalJournalEntry,它包含一些原始属性以及 BloodPressure 类(关联)的嵌套对象。在这里你可以看到这两个类:

类 MedicalJournalEntry:

@Entity
@Table(name="MED_JOURNAL_ENTRY")
public class MedicalJournalEntry extends JournalEntry


/*
 * The following attributes are inherited from the superclass JournalEntry
 * intJournalEntryId
 * datJournalEntryDate
 * tstmpJournalEntryCreateDate
 * tstmpJournalEntryUpdateDate
 * 
 * getters and setters are defined and implemented in the superclass JournalEntry as well
 * 
 */
@Embedded
private BloodPressure bloodPressure;

@ManyToOne
@JoinColumn(name = "JOURNAL_ID")
@JsonBackReference
private MedicalJournal medJournal; // bidirectional relationship with entity MedicalJournal

@Column(name="JOURNAL_ENTRY_PULSE")
private short shPulse; 
@Column(name="JOURNAL_ENTRY_HEIGHT")
@Min(value = 1, message="Die Größe muss größer als 1cm sein.")
@Max(value = 300, message="Die Größe muss kleiner als 300cm sein.")
private short shHeight; // in centimeters
@Column(name="JOURNAL_ENTRY_WEIGHT")
@Min(value = 1, message="Das Gewicht muss größer als 1kg sein.")
@Max(value = 500, message="Das Gewicht muss kleiner als 500kg sein.")
private short shWeight; // in kilograms
@Column(name="JOURNAL_ENTRY_BMI")
private float fltBmi;
@Column(name="JOURNAL_ENTRY_IS_SICK")
private boolean blnIsSick;

// constructors and methods ...

班级血压:

@Embeddable // is part of MedicalJournalEntry
public class BloodPressure 

public BloodPressure(int intSYS, int intDIA) 
    this.intSYS = intSYS;
    this.intDIA = intDIA;

@Column(name ="BLOOD_PRESSURE_SYS")
private int intSYS;
@Column(name = "BLOOD_PRESSURE_DIA")
private int intDIA;
// constructors and mehtods ...

我使用片段创建了一个表单。它对“普通”字段非常有效,但由于我添加了嵌套对象字段,Thymeleaf 甚至无法再创建保存表单的视图。当我想显示表单时,我总是收到以下错误:

处理器执行过程中出错

org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (模板:“create-medJournalEntry”

我的百里香叶形式如下:

    <form action = "#" th:action="@/medJourEntry/add" th:object=$medicalJournalEntry method ="post">

    <div th:replace="edit-medJournalEntry.html :: medEntryForm(medEntry=$#object)"></div>


    <button type="submit" class="btn btn-primary">Tagebucheintrag erstellen</button>

    <button type="reset" class="btn btn-primary">Felder zurücksetzen</button>

    </form>

以及导致问题的片段的相应内容:

        </div>

            <div class ="form-row">

                <div class="form-group col-md-4">

                    <label for="bloodpressureSys">Blutdruck systolisch</label>

                    <input type="text" th:field="*bloodPressure.intSys" class="form-control" id="bloodpressureSys" aria-describedby="bloodpressureSystHelp" placeholder="Systolischer Blutdruck">

                    <div th:if="$#fields.hasErrors('$medicalJournalEntry.bloodPressure.intSys')">
                        <div class="alert alert-danger" role="alert">
                            <p th:each="err : $#fields.errors('bloodPressure.intSys')" th:text="$err"></p>
                        </div>
                    </div>

                    <small id="bloodpressureSystHelp" class="form-text text-muted">Bitte tragen Sie den systolischen Blutdruck (in mmHg) ein.</small>

                </div>

            <div class="form-group col-md-4">

                    <label for="bloodpressureDia">Blutdruck Diastolisch</label>

                    <input type = "text" th:field="*bloodPressure.intDia" class="form-control" id="bloodpressureDia" aria-describedby="bloodpressureDiaHelp" placeholder="Diastolischer Blutdruck">

                    <small id="bloodpressureDiaHelp" class="form-text text-muted">Bitte tragen Sie den diastolischen Blutdruck (in mmHg) ein.</small>

            </div>
        </div>

这是我的控制器。它只返回包含新 MedicalJournalEntry 输入数据表单的视图:

@RequestMapping(value="/create", method = RequestMethod.GET)
public String showCreateMedicalJournalEntryForm(MedicalJournalEntry medicalJournalEntry) 

    return "create-medJournalEntry";

【问题讨论】:

澄清一下,只有在包含片段时才会发生这种情况?如果您在“模板”中包含 HTML,您不会遇到同样的问题吗?您能否为此分享您的控制器? 您需要包含整个堆栈轨道。它将描述错误是什么以及发生的位置。 另外,您的属性名为 intSYSintDIA,但在 html 中它们是 intSysintDia 是的,我也注意到了错误的属性名称,但这并没有解决问题。我还将我的控制器放入帖子中。事情是这样的:我假设 Thymeleaf 不能以一种形式创建 2 个对象。他们还在他们的文档中写道:thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#preface,引用:“一旦在
标记内,就不能指定其他 th:object 属性。这与 HTML 表单不能嵌套的事实一致。”我什至找不到像我想要做的那样与百里香叶建立关联的人。在我看来很疯狂
我不能再发布堆栈跟踪了,因为我改变了我的类结构。但我仍然想知道如何实现与 thymeleaf(嵌套对象)的关联。我的意思是,这必须以某种方式成为可能。否则 Thymeleaf 将是一项非常薄弱的​​技术^^。我只是在互联网上找不到任何信息。 【参考方案1】:

感谢所有试图帮助我的人!

我们刚刚发现了我们的问题。

MedicalJournalEntry 类的无参数构造函数缺少空的 BloodPressure 对象的构造。这是强制性的,否则基本上你会得到某种 NullPointerException,因为子对象不存在。

所以问题解决了。再次感谢大家,真的很感激! :)

【讨论】:

以上是关于使用 Thymeleaf 为嵌套对象创建表单的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何执行嵌套 Thymeleaf 循环以创建包含来自两个 JPA 表类的字段的表

Thymeleaf 表单不将对象返回给控制器类方法

如果表单输入没有明确使用它,如何设置Spring Form和Thymeleaf不更改作为模型属性添加的对象的字段?

Spring + Thymeleaf 绑定表单 NullpointerException

在 for 循环期间访问嵌套对象 VueJS

Angular 2 使用嵌套组件创建反应式表单