【问题标题】:Spring Nested object is getting null while submitting formSpring嵌套对象在提交表单时为空
【发布时间】:2023-03-22 04:40:01
【问题描述】:

我正在尝试使用 thymeleaf 发布数据,命令模型有两个嵌套对象,一个正在获取数据,而另一个正在获取 null。我很困惑,虽然使用相同的概念和代码,但幕后发生了什么。

请注意,我在日志中获取了 People 对象的数据,但没有获取 Project 对象的数据,尽管使用的是相同的代码。请帮忙。

表单片段。

<form th:fragment="form" method="post" th:object="${expense}" th:action="@{/createexpense}">

<input type="hidden" th:field="*{expenseId}" />
<div class="form-group">
  <label class="col-md-4 control-label" for="textarea">Expense Description</label>
  <div class="col-md-4">                     
    <textarea class="form-control" id="textarea" th:field="*{description}" name="textarea">Expense Description</textarea>
  </div>
</div>

<div class="form-group">
  <label class="col-md-4 control-label" for="textinput">Amount</label>  
  <div class="col-md-4">
  <input id="textinput" name="textinput" type="text" placeholder="Enter Amount" th:field="*{amount}" class="form-control input-md"> 
 </div>
</div>


<div class="form-group">
  <label class="col-md-4 control-label" for="textinput">Project</label>  
  <div class="col-md-4">
  <select class="form-control" id="sel1" th:field="*{project}">
    <option th:each="project: ${projects}" th:value="${{project.projectId}}" th:text="${project.name}">1</option>
  </select>
  </div>
</div>

<div class="form-group">
  <label class="col-md-4 control-label" for="textinput">People</label>  
  <div class="col-md-4">
  <select class="form-control" id="sel1" th:field="*{people}" >
   <option th:each="people: ${peoples}" th:value="${people.id}" th:text="${people.name}">1</option>
  </select>
  </div>
</div>

<div class="form-group">
  <label class="col-md-4 control-label" for="textinput">Expense Type</label>  
  <div class="col-md-4">

  <select class="form-control" id="sel1" th:field="*{expenseType}">
    <option th:each="exp:  ${expenseTypes}" th:value="${exp}" th:text="${exp}">1</option>
  </select>
  </div>
</div>

<div class="form-group">
  <label class="col-md-4 control-label" for="textinput">Create 
Expense</label>  
  <div class="col-md-4">
      <input type="submit" class="btn btn- danger" value="Submit"/
 </div>
</div>

模型 Bean 类

@Data
@JsonIgnoreProperties(value = {"createdAt", "updatedAt"},
        allowGetters = true)
@Entity
public class Expense {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long expenseId;

    @Lob
    private String description;

    @OneToOne
    @Cascade(CascadeType.ALL)
    private People people;

    private Double amount;

    @Temporal(TemporalType.TIMESTAMP)
    @CreatedDate
    private Date createdAt;

    @Temporal(TemporalType.TIMESTAMP)
    @LastModifiedDate
    private Date updatedAt;


    @ManyToOne
    @Cascade(CascadeType.ALL)
    private Project project;

    @Enumerated(EnumType.STRING)
    private ExpenseType expenseType;

    public Expense(String description, Double expense) {
        this.description = description;
        this.amount = expense;
    }

    public Expense() {
    }


    public void setCreatedAt(Date createdAt) {
        this.createdAt = new Date();
    }

    public Date getUpdatedAt() {
        return updatedAt;
    }

    @PreUpdate
    public void setUpdatedAt() {
        this.updatedAt = new Date();
    }

}

控制器片段

@PostMapping(path="/createexpense")
    public Expense addExpense(@ModelAttribute("expense") Expense expense ,BindingResult result){

    log.debug(expense.toString());
    expense.setPeople(peopleService.getPeople(expense.getPeople().getId()));
    expense.setProject(flatProjectService.getFlatProjectById(expense.getProject().getProjectId()));
    return expenseService.createExpense(expense);
}

@GetMapping(path="/createexpense")
public ModelAndView addExpense(ModelAndView modal){
    //adding projects list and people list in expense view
    modal.addObject("projects", flatProjectService.getAllProjects());
    modal.addObject("peoples", peopleService.getAllPeoples());
    modal.setViewName("createexpense");
    modal.addObject("expense", new Expense());
    modal.addObject("expenseTypes", ExpenseType.values());
    return modal;
}

错误日志

2018-07-22 18:22:44.010 DEBUG 25500 --- [nio-8080-exec-5] c.d.b.controller.HomeController          : Expense(expenseId=null, description=hello, people=People(id=2, name=Avinash, peopleType=null, phoneNo=9504974665, address=Beside Maa Clinic, expense=[], createdDate=2009-06-01 13:45:30.0, updatedDate=2009-06-01 13:45:30.0), amount=5000.0, createdAt=null, updatedAt=null, project=null, expenseType=PAID)
2018-07-22 18:22:44.090 ERROR 25500 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

java.lang.NullPointerException: null

【问题讨论】:

  • 你能补充一下你是如何进行 ajax 调用的吗。在控制台中查看 JSON 是什么在 POST 调用中发送
  • 我没有使用 ajax,虽然这是发送给控制器的; expenseId=&amp;description=hello&amp;amount=7000&amp;project=2&amp;people=2&amp;expenseType=PAID&amp;textinput=
  • 您将人员作为 2 传递,但在控制器中您已编写了费用.getPeople().getId()。这是行不通的。因此,您的 POST 调用格式将与您的费用对象不匹配
  • People对象被完美解析,可以在日志中看到,Ashish,但问题是为什么Project对象没有被解析。有没有其他方法可以做到这一点?
  • 请发布异常的完整堆栈跟踪,并指出堆栈跟踪和您发布的代码中的匹配行。

标签: spring spring-mvc spring-data-jpa thymeleaf spring-form


【解决方案1】:

查看您的 HTML 逻辑。我怀疑问题出在项目循环中

您正在定义th:field="*{project}"
但在选项中使用pro

理想情况下应该是这样的

<div class="form-group">
  <label class="col-md-4 control-label" for="textinput">Project</label>  
  <div class="col-md-4">
  <select class="form-control" id="sel1" th:field="*{project}">
    <option th:each="project: ${projects}" th:value="${project.projectId}" 
   th:text="${pro.name}">1</option>
  </select>
</div>
</div>

【讨论】:

  • 试过了,没有运气。
  • 在逻辑上存在一些问题,您如何发送 HTML 中的显示数据或发送 Data 。不在后端...
  • Ashish,我已经编辑了我的问题,现在整个表格都发布了。
  • 嘿,你有 th:value="${{project.projectId}}" 不应该是 th:value="${project.projectId}" 单花括号
  • 试过了,但问题没有解决。我添加了一个字段 projectId,因此继续解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-17
  • 1970-01-01
  • 2014-03-16
  • 2015-05-31
  • 2017-05-09
相关资源
最近更新 更多