我正在做一个Spring框架项目。为了快速开发过程,我使用Spring Roo(1.3.2)。对于一些实体,我需要存储创建时间和最后一次更新时间。我在Spring Roo教程项目上做了几个实验,这是其中一个实体和我正在尝试的方法。
package com.springsource.roo.pizzashop.domain;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.jpa.activerecord.RooJpaActiveRecord;
import org.springframework.roo.addon.tostring.RooToString;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.springframework.format.annotation.DateTimeFormat;
@RooJavaBean
@RooToString
@RooJpaActiveRecord
public class Topping {
/**
*/
@NotNull
@Size(min = 2)
private String name;
/**
*/
@Temporal(TemporalType.TIMESTAMP)
@DateTimeFormat(style = "M-")
private Date createdAt;
/**
*/
@Temporal(TemporalType.TIMESTAMP)
@DateTimeFormat(style = "M-")
private Date updatedAt;
@PrePersist
protected void onCreate() {
createdAt= new Date();
}
@PreUpdate
protected void onUpdate() {
updatedAt = new Date();
}
}
当我创建一个对象(Topping)时,它为createdAt获得正确的值,并为updatedAt留下"NULL"。完美!这是必须的方式!
但是当我更新对象(Topping)时,它获得了updatedAt的正确值并失去了createdAt (NULL)的值。
问题是,当我更新对象时,我失去了createdAt的值。
你能告诉我为什么我有这种行为吗?你能帮我想出一个可能的解决办法吗?
然而,createdAt和updatedAt字段不需要出现在"视图"(create. view)中。jspx, update.jspx),因此我将其呈现属性设置为false。这些是用于创建和更新的表单。
create.jspx
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:field="urn:jsptagdir:/WEB-INF/tags/form/fields" xmlns:form="urn:jsptagdir:/WEB-INF/tags/form" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:spring="http://www.springframework.org/tags" version="2.0">
<jsp:directive.page contentType="text/html;charset=UTF-8"/>
<jsp:output omit-xml-declaration="yes"/>
<form:create id="fc_com_springsource_roo_pizzashop_domain_Topping" modelAttribute="topping" path="/toppings" render="${empty dependencies}" z="w4+E4tQPCNRPSYVWPNOBUuf9zNE=">
<field:input field="name" id="c_com_springsource_roo_pizzashop_domain_Topping_name" min="2" required="true" z="GRdEGRLiZ0QLjBH0pTEOZ252BD8="/>
<field:datetime dateTimePattern="${topping_ts_date_format}" field="ts" id="c_com_springsource_roo_pizzashop_domain_Topping_ts" render="false" z="user-managed"/>
<field:datetime dateTimePattern="${topping_updated_date_format}" field="updated" id="c_com_springsource_roo_pizzashop_domain_Topping_updated" render="false" z="user-managed"/>
</form:create>
<form:dependency dependencies="${dependencies}" id="d_com_springsource_roo_pizzashop_domain_Topping" render="${not empty dependencies}" z="bkqRYdlfs3kDAjK51P0O+7NiahE="/>
</div>
update.jspx
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:field="urn:jsptagdir:/WEB-INF/tags/form/fields" xmlns:form="urn:jsptagdir:/WEB-INF/tags/form" xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
<jsp:directive.page contentType="text/html;charset=UTF-8"/>
<jsp:output omit-xml-declaration="yes"/>
<form:update id="fu_com_springsource_roo_pizzashop_domain_Topping" modelAttribute="topping" path="/toppings" versionField="Version" z="YGl9ujJNQw182uzoCDgi1FdiafQ=">
<field:input field="name" id="c_com_springsource_roo_pizzashop_domain_Topping_name" min="2" required="true" z="GRdEGRLiZ0QLjBH0pTEOZ252BD8="/>
<field:datetime dateTimePattern="${topping_ts_date_format}" field="ts" id="c_com_springsource_roo_pizzashop_domain_Topping_ts" render="false" z="user-managed"/>
<field:datetime dateTimePattern="${topping_updated_date_format}" field="updated" id="c_com_springsource_roo_pizzashop_domain_Topping_updated" render="false" z="user-managed"/>
</form:update>
</div>
render="false" on fields标签使得这些字段不会被包含在页面上。因此,在POST请求中,该值缺失并且Spring Binding不填充它(取Binding进程创建实体的新实例的计数,不从DB中获取它)。这使得合并操作将缺失值设置为null
。
关于这个的更多信息,你可以阅读:
- Spring MVC 3.0:如何绑定到持久对象
- 是否有可能在使用Spring MVC与JPA的实体上仅更新属性的子集?
最简单的解决方法是将此值包含在编辑表单的隐藏输入中。
另一方面,看看gvNIX的审计特性。该特性包括审计(存储创建/更新时间戳和执行该操作的用户)和修订日志(使用Hibernate Envers)。
祝你好运!