Spring Data Repository 使用更新的审计字段保存不返回实例
Posted
技术标签:
【中文标题】Spring Data Repository 使用更新的审计字段保存不返回实例【英文标题】:Spring Data Repository Save Not Returning Instance With Updated Audit Fields 【发布时间】:2013-12-21 08:46:36 【问题描述】:为什么 repository.save(myEntity) 不返回具有更新审计字段的更新实体?
来自 MyEntityRepository.save(myEntity) 以及随后来自 MyEntityService.save(myEntity) 的结果实例没有更新的 updatedOn 日期。我已经验证这在数据库中设置正确,所以我知道审计正在工作。返回的实例的 updatedOn 日期对于插入是正确的,但对于更新不正确。我宁愿不必在每次保存后立即执行 findById,特别是如果意图是 save() 返回更新后的附加实例。
假设 updatedOn 的设置是通过 @PreUpdate 钩子发生的,并且这个钩子是在通过 repository.save() 调用 entityManager.merge() 期间触发的,我不明白为什么不会在返回的值上设置该值实例。
示例代码:
@Entity
@DynamicUpdate
@DynamicInsert
@Table(name = "my_entity", schema = "public")
@SequenceGenerator(name = "pk_sequence", sequenceName = "my_entity_seq", allocationSize = 1)
@AttributeOverrides(@AttributeOverride(name = "id", column = @Column(name = "id", columnDefinition = "int")))
@EntityListeners(AuditingEntityListener.class)
public class MyEntity
protected Integer id;
@LastModifiedDate
private Date updatedOn;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pk_sequence")
@Column(name = "id", nullable = false, columnDefinition = "bigint")
public Integer getId()
return id;
public void setId(Integer id)
this.id = id;
@Version
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "updated_on")
public Date getUpdatedOn()
return updatedOn;
public void setUpdatedOn(Date updatedOn)
this.updatedOn = updatedOn;
public interface MyEntityRepository extends JpaRepository<MyEntity, Integer>
@Service
@Transactional(readOnly = true)
public class MyEntityService
@Autowired
private MyEntityRepository repository;
@Transactional
public MyEntity save(MyEntity myEntity)
return repository.save(myEntity);
【问题讨论】:
您是否调试到AuditingEntityListener.touchForUpdate(…)
并查看是否调用了该方法?您确定实体实际上包含更改吗?如果持久性提供程序在实体上找不到任何更改,它甚至可能不会触发事件,即使我们调用EntityManager.merge(…)
。
是的,我有,它正在被调用。我实际上已经使用 AuditingEntityListener 和我自己的 @PreUpdate 钩子实现了它。两种方法都有效 - 更改以正确的 updatedOn 日期保存到数据库中。但是从 repository.save 或 repository.saveAndFlush 返回的实例没有这些更改的审计字段(但是所有其他更改的数据都正确反映)。
这很奇怪。您是否有机会将其归结为一个小测试用例并针对 Spring Data JPA 提交 JIRA?了解您使用的 JPA 提供程序也很有用。
我会这样做的。提供者是 Hibernate 4.2.6。
【参考方案1】:
我遇到了同样的问题。
就我而言,帮助我解决这个问题的重要项目是:
1)使用repository.saveAndFlush(...)
方法
2) 使用findAllById()
或findByYourOwnQuery()
(注解@Query
)。
总的来说,我的测试用例如下所示:
UserAccount userAccount = UserAccount.builder().username(username).build();
userAccountRepository.saveAndFlush(userAccount);
final LocalDateTime previousUpdateDate = userAccount.getUpdateDate();
....
List<BigInteger> ids = Arrays.asList(userAccountId);
UserAccount updatedUserAccount = userAccountRepository.findAllById(ids).get(0); // contains updated Audit data fields
...
assertThat(actual.getUpdateDate(), is(greaterThan(previousUpdateDate))); // true
您不应该使用 repository.findOne(...)
的重要一点,因为它缓存了对对象的引用 - read more。
【讨论】:
【参考方案2】:我遇到了完全相同的问题。我通过使用修复它,
repository.saveAndFlush(myEntity);
而不是
repository.save(myEntity);
【讨论】:
以上是关于Spring Data Repository 使用更新的审计字段保存不返回实例的主要内容,如果未能解决你的问题,请参考以下文章
Spring Data Redis - 对 Repository 的 @Transactional 支持
Spring Data Repository 使用更新的审计字段保存不返回实例
Spring Data JPA Custom Repository
Spring Entity Manager 和 Spring Data Repository 有啥区别?