标记为 updatable=false 的 Spring 数据审计字段在更新时不会在返回的实体上设置。



我正在使用Spring Data的注释在保存或更新时将审计数据添加到我的实体中。当我创建实体时,createdBycreatedDatelastModifiedBylastModifiedDate设置在repository.save()返回的对象上。

ResourceEntity(id=ebbe1f3d-3359-4295-8c83-63eab21c4753, createdDate=2018-09-07T21:11:25.797, lastModifiedDate=2018-09-07T21:11:25.797, createdBy=5855070b-866f-4bc4-a18f-26b54f896a4b, lastModifiedBy=5855070b-866f-4bc4-a18f-26b54f896a4b)

不幸的是,当我调用repository.save()来更新现有实体时,返回的对象没有设置createdBycreatedDate

ResourceEntity(id=ebbe1f3d-3359-4295-8c83-63eab21c4753, createdDate=null, lastModifiedDate=2018-09-07T21:12:01.953, createdBy=null, lastModifiedBy=5855070b-866f-4bc4-a18f-26b54f896a4b)

所有字段在数据库中都设置正确,并且调用repository.findOne()在我的服务类之外返回一个正确设置了所有字段的对象。

ResourceEntity(id=ebbe1f3d-3359-4295-8c83-63eab21c4753, createdDate=2018-09-07T21:11:25.797, lastModifiedDate=2018-09-07T21:12:01.953, createdBy=5855070b-866f-4bc4-a18f-26b54f896a4b, lastModifiedBy=5855070b-866f-4bc4-a18f-26b54f896a4b)

但是,如果我在调用repository.save()更新实体后立即在服务中调用repository.findOne(),我也会得到一个对象,createdBycreatedDate设置为 null。

这是我的实体:

@Entity(name = "resource")
@EntityListeners(AuditingEntityListener.class)
@Table(name = "resource")
@Data
@EqualsAndHashCode(of = "id")
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ResourceEntity {
@Id
@org.hibernate.annotations.Type(type = "org.hibernate.type.PostgresUUIDType")
private UUID id;
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
@CreatedBy
@Column(nullable = false, updatable = false)
@org.hibernate.annotations.Type(type = "org.hibernate.type.PostgresUUIDType")
private UUID createdBy;
@LastModifiedBy
@org.hibernate.annotations.Type(type = "org.hibernate.type.PostgresUUIDType")
private UUID lastModifiedBy;
}

这是我的服务:

@Component
public class ResourceService {
@Autowired
private ResourceRepository resourceRepository;
public ResourceEntity createResource(ResourceEntity resourceEntity) {
return saveResource(resourceEntity);
}
public ResourceEntity updateResource(ResourceEntity resourceEntity) {
return saveResource(resourceEntity);
}
public ResourceEntity getResource(UUID resourceId) {
return resourceRepository.findOne(resourceId);
}
private ResourceEntity saveResource(ResourceEntity resourceEntity) {
ResourceEntity savedResourceEntity = resourceRepository.save(resourceEntity);
return savedResourceEntity;
}
}

这是我的测试:

def "Test update"() {
given:
UUID id = aRandom.uuid()
Resource resource = aRandom.resource().id(id).build()
Resource savedResource = resourceClient.createResource(resource)
when:
Resource updatedResource = aRandom.resource().id(id).build()
updatedResource = resourceClient.updateResource(updatedResource)
then:
Resource result = resourceClient.getResource(id)
assert result.id == updatedResource.id
assert result.createdBy == updatedResource.createdBy
assert result.creationDate == updatedResource.creationDate
assert result.lastModifiedBy == updatedResource.lastModifiedBy
assert result.lastModifiedDate == updatedResource.lastModifiedDate
}

在原始问题多年后,这仍然是一个问题。

虽然不是一个完美的解决方案,但我最终获取(通过findById()(现有实体并在执行更新之前手动设置新实体上的@CreatedBy@CreatedDate字段。令人惊讶和沮丧的是,JPA的审计框架并没有自动处理这个问题,也没有提供更好的方法来实现这一目标。

当我需要添加审核信息时,我之前尝试过这样。

我有这样的DataConfig课。

@Configuration
@EnableJpaAuditing
public class DataConfig {
@Bean
public AuditorAware<UUID> auditorProvider() {
return new YourSecurityAuditAware();
}
@Bean
public DateTimeProvider dateTimeProvider() {
return () -> Optional.of(Instant.from(ZonedDateTime.now()));
}
}

现在,您需要AuditorAware类来获取审核信息。 所以这个类将是这样的;

public class XPorterSecurityAuditAware implements AuditorAware<UUID> {
@Override
public Optional<UUID> getCurrentAuditor() {
//you can change UUID format as well
return Optional.of(UUID.randomUUID());
}
}

希望这对您有所帮助。

相关内容

  • 没有找到相关文章

最新更新