我使用SpringBoot和JPA / Hibernate,我想添加审核。
我创建了一个抽象实体,其中包含以下内容:
@CreatedDate
@NotNull
@Column(columnDefinition = "DATETIME(3)", updatable = false)
private ZonedDateTime createdDate;
@LastModifiedDate
@Column(columnDefinition = "DATETIME(3)")
private ZonedDateTime lastModifiedDate;
该应用程序
我在实体上使用简单的CRUD开发RESTful API。 我的资源(控制器)正在jpa存储库上使用save()方法进行创建和更新
问题:
当我在实体上调用repository.save()来更新它时," createdDate"被忽略(这是正常的)但是该方法返回的实体具有" createdDate"设置为null。
然后将实体放入缓存中,下一个get也将其createdDate值设置为null。
如何在不允许修改字段createdDate和使用JpaCrudRepository的情况下更新实体?
更新
存储库定义:
public interface ModelRepository extends JpaRepository<Model, Long> {
REST控制器:
public ResponseEntity<Model> createModel(@RequestBody Model model) throws URISyntaxException {
Model result = modelRepository.save(model);
return ResponseEntity.created(new URI("/api/v1/models/" + result.getId()))
.body(result);
}
端点返回的Json包含&#34; createdDate:null&#34;
更新2
要解决此问题,我已经创建了这样的服务:
@Override
public Model save(Model model) {
Model result = modelRepository.save(model);
return result;
}
@Override
public Model update(Long id, Model model) {
Model existingModel = modelRepository.findOne(id);
if (existingModel == null) {
return null;
}
// Non updatable fields
model.setId(id);
model.setCreatedDate(existingModel.getCreatedDate());
Model result = modelRepository.save(model);
return result;
}
为了使这项工作,我还删除了&#34; updatable = false&#34;来自createdDate字段,以防止结果在保存后具有空日期。
我不明白拥有&#34; updatable = false&#34;如果我们必须在之后手动处理它。
答案 0 :(得分:1)
也许@CreatedDate(org.springframework.data.annotation.CreatedDate)是错误的注释?我的小型spring-boot JPA / Hibernate CRUD服务器在创建日期列上使用注释@CreationTimestamp(org.hibernate.annotations.CreationTimestamp):
@CreationTimestamp
@Column(name = "CREATED_DATE", nullable = false, updatable = false, columnDefinition = "TIMESTAMP")
private Date created;
请求以null创建日期到达。在调用repo.save()方法时,会发生魔法,并且生成的域对象具有非null创建日期。我没有摆弄实体经理,没有同花顺,nada。
我注意到尽管注释了&#34; updatable = false&#34;在列上,更改现有实体上的创建日期值并调用repo.save()方法会保持该更改而不会抱怨。这让我感到惊讶。
答案 1 :(得分:0)
如果我们暂时只考虑简单的Hibernate,那么在映射上指定updatable=false
是完全合法的,但显然必须在某处初始化该值,以便Hibernate知道插入时列中放置的值。 / p>
您自己设置值的解决方案正是普通Hibernate用户必须做的事情。
但是我注意到你的模型使用了@CreatedDate
注释,从我的简短的谷歌搜索看起来是Spring Data公开的并且与Hibernate无关的东西。这对我来说意味着可能没有在这里正确配置。
我从未在Spring数据中使用此功能,但您可以找到另一篇帖子here。也许它可以帮助突出显示您的配置可能已关闭的位置以及@CreatedDate
注释未按预期初始化字段的原因。
<强>更新强>
如果外部源为您提供了您需要在现有实体顶上应用的状态(例如update
方法的情况),则首先需要检索实体并相应地覆盖您的输入。< / p>
// Some controller or business method
public Object updateModel(Model input) {
final Model model = modelRepository.findOne( input.getId() );
if ( model != null ) {
// replicate business case fields
// sometimes this can be done using frameworks like ObjectMapper, etc.
// this is just a simple case.
model.setField1( input.getField1() );
model.setField2( input.getField2() );
return modelRepository.update( model );
}
throw new UnknownObjectException( "No Model found with id: " + input.getId() );
}
希望有所帮助。
答案 2 :(得分:0)
我能够通过刷新并清除entityManager然后重新选择数据来解决这个问题。
entityManager.flush(); entityManager.clear();