【问题标题】:Spring filed with date/time is null when the form is submited提交表单时,带有日期时间的 Spring 文件为空
【发布时间】:2019-12-02 15:21:40
【问题描述】:

我的控制器中有两个映射。这是一个 GET 映射:

@RequestMapping(value="/items/book-list/edit", method = RequestMethod.GET)
public String showEditBookPage(@RequestParam Long id, ModelMap model){
    Book book = bookService.findBookById(id);
    model.addAttribute("editForm", book);
    LOG.info("Logged modified date once page is loaded: " + book.getModifyDate());
    return "admin/book";
}

这个映射只是为了显示一个小表单的 book.jsp 页面。

我还有另一个相同值的映射,但使用 POST 方法,用于提交表单。

 @RequestMapping(value="/items/book-list/edit", method = RequestMethod.POST)
public String updateBook(@ModelAttribute("editForm") @Valid Book bookForm, BindingResult result, ModelMap model){
    if(result.hasErrors()){
        return "/admin/book";
    }

    LOG.info("Logged modified date before Save object: " + bookForm.getModifyDate());
    LOG.info("Logged author before Save object: " + bookForm.getAuthor());

    bookService.saveBook(bookForm);

    LOG.info("Logged modified date after Save object: " + bookForm.getModifyDate());
    LOG.info("Logged author after Save object: " + bookForm.getAuthor());

    return "admin/book";
}

我的 book.jsp:

<form:form method="post" modelAttribute="editForm" >
        <div class="row border py-4">
            <div class="col-sm-6">
                <spring:bind path="title">
                    <div class="form-group">
                        <form:label path="title" for="title">Book title</form:label>
                        <form:input path="title" type="text" class="form-control" id="title" cssErrorClass="form-control border border-danger"/>
                    </div>
                </spring:bind>
                <spring:bind path="author">
                    <div class="form-group">
                        <form:label path="author" for="author">Author</form:label>
                        <form:input path="author" type="text" class="form-control" id="author" cssErrorClass="form-control border border-danger"/>
                    </div>
                </spring:bind>
                <p class="form-group">Last modified date: ${editForm.modifyDate}</p>

            </div>
    </form:form>

图书实体:

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="id", updatable = false, nullable = false)
private long id;

@Column(nullable = false)
@NotEmpty(message = "This field is required.")
private String title;

@Column(nullable = false)
private int quantity;

@Column(nullable = false)
private int availability;

@UpdateTimestamp
private LocalDateTime modifyDate;

@CreationTimestamp
@Column(name="create_date", updatable = false, nullable = false)
private LocalDateTime createDate;

来自 GET 方法的日志:

2019-07-24 14:32:57.065 DEBUG 16119 --- [nio-8080-exec-6] org.hibernate.SQL                        : select book0_.id as id1_0_0_, book0_.availability as availabi2_0_0_, book0_.create_date as create_d3_0_0_, book0_.modify_date as modify_d4_0_0_, book0_.quantity as quantity5_0_0_, book0_.title as title6_0_0_, book0_.author as author7_0_0_ from book book0_ where book0_.id=?
Hibernate: select book0_.id as id1_0_0_, book0_.availability as availabi2_0_0_, book0_.create_date as create_d3_0_0_, book0_.modify_date as modify_d4_0_0_, book0_.quantity as quantity5_0_0_, book0_.title as title6_0_0_, book0_.author as author7_0_0_ from book book0_ where book0_.id=?
2019-07-24 14:32:57.068 TRACE 16119 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [10003]
2019-07-24 14:32:57.072 TRACE 16119 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([availabi2_0_0_] : [INTEGER]) - [56]
2019-07-24 14:32:57.072 TRACE 16119 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([create_d3_0_0_] : [TIMESTAMP]) - [2019-07-24T14:32:47.161]
2019-07-24 14:32:57.073 TRACE 16119 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([modify_d4_0_0_] : [TIMESTAMP]) - [2019-07-24 14:32:47.161]
2019-07-24 14:32:57.073 TRACE 16119 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([quantity5_0_0_] : [INTEGER]) - [56]
2019-07-24 14:32:57.073 TRACE 16119 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([title6_0_0_] : [VARCHAR]) - [Book title]
2019-07-24 14:32:57.073 TRACE 16119 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([author7_0_0_] : [VARCHAR]) - [Philippa Gregory]
2019-07-24 14:32:57.078  INFO 16119 --- [nio-8080-exec-6] c.s.s.web.controller.AdminController     : Logged modified date once page is loaded: 2019-07-24 14:32:47.161

POST方法的日志

2019-07-24 14:34:12.840 DEBUG 16119 --- [nio-8080-exec-5] org.hibernate.SQL                        : select book0_.id as id1_0_0_, book0_.availability as availabi2_0_0_, book0_.create_date as create_d3_0_0_, book0_.modify_date as modify_d4_0_0_, book0_.quantity as quantity5_0_0_, book0_.title as title6_0_0_, book0_.author as author7_0_0_ from book book0_ where book0_.id=?
Hibernate: select book0_.id as id1_0_0_, book0_.availability as availabi2_0_0_, book0_.create_date as create_d3_0_0_, book0_.modify_date as modify_d4_0_0_, book0_.quantity as quantity5_0_0_, book0_.title as title6_0_0_, book0_.author as author7_0_0_ from book book0_ where book0_.id=?
2019-07-24 14:34:12.840 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [10003]
2019-07-24 14:34:12.841 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([availabi2_0_0_] : [INTEGER]) - [56]
2019-07-24 14:34:12.841 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([create_d3_0_0_] : [TIMESTAMP]) - [2019-07-24T14:32:47.161]
2019-07-24 14:34:12.841 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([modify_d4_0_0_] : [TIMESTAMP]) - [2019-07-24 14:32:47.161]
2019-07-24 14:34:12.841 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([quantity5_0_0_] : [INTEGER]) - [56]
2019-07-24 14:34:12.841 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([title6_0_0_] : [VARCHAR]) - [Book title]
2019-07-24 14:34:12.841 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([author7_0_0_] : [VARCHAR]) - [Philippa Gregory]
2019-07-24 14:34:12.843  INFO 16119 --- [nio-8080-exec-5] c.s.s.web.controller.AdminController     : Logged modified date before Save object: null
2019-07-24 14:34:12.843  INFO 16119 --- [nio-8080-exec-5] c.s.s.web.controller.AdminController     : Logged author before Save object: Book title 2
2019-07-24 14:34:12.874 DEBUG 16119 --- [nio-8080-exec-5] org.hibernate.SQL                        : update book set availability=?, modify_date=?, quantity=?, title=?, author=? where id=?
Hibernate: update book set availability=?, modify_date=?, quantity=?, title=?, author=? where id=?
2019-07-24 14:34:12.876 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [56]
2019-07-24 14:34:12.877 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [TIMESTAMP] - [Wed Jul 24 14:34:12 CEST 2019]
2019-07-24 14:34:12.877 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [INTEGER] - [56]
2019-07-24 14:34:12.877 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [VARCHAR] - [Book title 2]
2019-07-24 14:34:12.878 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [5] as [VARCHAR] - [Philippa Gregory]
2019-07-24 14:34:12.878 TRACE 16119 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [6] as [BIGINT] - [10003]
2019-07-24 14:34:12.884  INFO 16119 --- [nio-8080-exec-5] c.s.s.web.controller.AdminController     : Logged modified date after Save object: null
2019-07-24 14:34:12.885  INFO 16119 --- [nio-8080-exec-5] c.s.s.web.controller.AdminController     : Logged author after Save object: Book title 2

提交表单后,“modifyDate”字段为空,而“title”则正常。有人可以向我解释为什么吗?这显示在控制台日志中。

查看:

Before submit

After submit

【问题讨论】:

    标签: java spring hibernate jsp jpa


    【解决方案1】:

    尝试为 LocalDateTime 字段显式添加反序列化器:

    @JsonDeserialize(using = LocalDateTimeDeserializer.class)  
    @CreationTimestamp
    @Column(name="create_date", updatable = false, nullable = false)
    private LocalDateTime createDate;
    

    还有你的反序列化类:

    public class LocalDateTimeDeserializer extends StdDeserializer<LocalDateTime> {
    
        @Override
        public LocalDate deserialize(JsonParser jsonParser, DeserializationContext ctx)
                throws IOException, JsonProcessingException {
            // parse the String date into LocalDateTime object as it fits you
        }
    
    }
    

    【讨论】:

      【解决方案2】:
      @UpdateTimestamp
      private LocalDateTime modifyDate;
      

      这样就可以了

      【讨论】:

      • 我已经有了这个注释。抱歉,我将 LocalDateTime 更改为 Date 只是为了测试,但结果是一样的。我已经更新了有问题的代码。
      【解决方案3】:

      您忘记在 My book.jsp 中添加 modify_date 字段:因为只有字段日期会发布,因为它是新请求,并且您保存在模型中的所有旧字段都不会随请求一起发布。所以有两个选项添加输入文本字段来更改日期。

      或者您将在保存之前手动设置日期

       bookForm.setModifyDate(new Date());
       bookService.saveBook(bookForm); 
      

      如果你想知道本地日期和时间,也可以添加@UpdateTimestamp

      @UpdateTimestamp
      private LocalDateTime modifyDate;
      

      【讨论】:

      • 嗨!嗯,但我的 modifyDate 字段上方已经有注释 @UpdateTimestamp。该日期已正确保存在数据库中,但在模型/视图中不可见。我有这样的解决方法:在 bookService.saveBook(bookForm); 之后我可以像这样添加一个新的modelAttribute: model.addAttribute("modifyDate",bookService.findBookById(bookForm.getId()).getModifyDate());这有效。但不明白为什么“TITLE”不为空而“MODIFYDATE”为空。
      • 这行代码是否不起作用

        上次修改日期:${editForm.modifyDate}

      • 您是否在您的图书实体中实现了 Serializable 接口,如果您没有实现,请实现它,然后检查
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-18
      • 2012-01-01
      • 1970-01-01
      • 2021-10-15
      • 2013-07-02
      相关资源
      最近更新 更多