我有一个实体类需要进行审计:
@Data // Lombok for getters/setters
@Entity
public class EventEntity {
@Id
private Long id;
@CreatedBy
private String createdId;
private LocalDateTime creationTimestamp; // @CreatedDate or @CreationTimestamp
@LastModifiedBy
private String modifiedId;
private LocalDateTime lastModifiedTimestamp; // @LastModifiedDate or @UpdateTimestamp
// other fields
}
我有一个用于数据库操作的 JpaRepository
:
public interface EventRepository extends JpaRepository<EventEntity, Long> {
// Empty
}
有这些注释,我不确定应该使用哪个日期注释:
org.springframework.data.annotation.CreatedBy
org.springframework.data.annotation.CreatedDate
org.hibernate.annotations.CreationTimestamp
org.springframework.data.annotation.LastModifiedBy
org.springframework.data.annotation.LastModifiedDate
org.hibernate.annotations.UpdateTimestamp
对于 @CreatedBy
/ @LastModifiedBy
字段,我已经根据文档实现了 org.springframework.data.domain.AuditorAware
,它只返回一个常量:
@Component("auditor")
public class CustomAuditorAware implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
return Optional.of("ID");
}
}
我已启用了JPA审计:
@Configuration
@EnableJpaAuditing("auditor")
public class AppConfig {
}
这是我尝试将数据持久化到数据库的方法:
EventEntity eventEntity = eventRepository.findById("ID") // returns Optional
.orElse(new EventEntity());
eventEntity.setSomeField("New Value");
eventRepository.save(eventEntity);
情况1:EventEntity是新的
调用无参构造函数,现在eventEntity
处于瞬态状态。执行save()
方法将执行select
查询,然后是一个update
查询,这将导致以下错误信息:
java.sql.BatchUpdateException: Cannot insert the value NULL into column 'CREATED_ID'
情境二:EventEntity已经存在
eventEntity
现在处于分离状态。审核字段已经填充完毕。 save()
方法执行一个update
查询,但是没有更改任何审核字段。
理想解决方案
我并不关心任何现有数据字段,只要已经存在就进行更新。因此,理想情况下,我不需要调用findById()
方法。我将创建一个处于瞬态状态的EventEntity
,它将保留createdId
和creationTimestamp
数据。就像上面说的一样:
EventEntity eventEntity = new EventEntity();
eventEntity.setSomeField("New Value");
eventRepository.save(eventEntity);
我的问题
我期望的审计字段都没有按照预期工作。我该如何让它正常工作?
我应该使用哪个审计日期注释?Spring JPA 还是 Hibernate?我已经尝试了两种设置但都没有成功。每种方法有什么不同呢?
版本信息:
- Spring Boot 2.1
- Hibernate 5.3.10.final