在Spring JPA中,我没有找到任何有关仅在字段修改时才保存实体的内容
从 JPA 获取记录后,在保存实体之前如何验证字段是否有修改/更改。 这就是我的做法
在
hasModifications
功能中我可以比较如果obj.field!=cloneObject.field
然后只保存
Class obj = repository.findById(id);
Class cloneObj = cloneObject(obj);
process(obj);
if (hasModifications(obj,cloneObj))
repository.save(obj);
else
//don't save
我尝试在类级别添加
@DynamicUpdate
注释。但这没有用。还有其他干净的方法可以做到这一点吗?
编辑: 我问这个是因为我在 MySql DB 中有一个名为 last_updated_at 的字段。每当我调用保存时,该字段都会使用当前时间戳进行更新,但不会更新其他字段值。 所以这就是我问这个问题的原因 这是表定义
'CREATE TABLE `username` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`info` mediumtext,
`status` varchar(255) NOT NULL,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`version` int NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_updated_at` (`updated_at`),
KEY `idx_created_at` (`created_at`)
)
编辑2: 我尝试将
@Trasactional
放在该方法上,并删除克隆和保存调用。但 update_at 仍在数据库中更新
@Transactional
public someMethod(){
Class obj = repository.findById(id);
process(obj);
}
这是我的 obj 实体
@Entity
@Table(name = "gratification_entity_task")
@JsonIgnoreProperties(
value = {"createdAt", "updatedAt"},
allowGetters = true)
@EntityListeners(AuditingEntityListener.class)
public class GratificationEntityTask {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(EnumType.STRING)
private TaskStatus status;
@Convert(converter = InfoConverter.class)
private Info info;
@CreatedDate
private Date createdAt;
@LastModifiedDate
private Date updatedAt;
@Version
private Integer version;
private int retryCount;
@Enumerated(EnumType.STRING)
private BeneficiaryType beneficiaryType;
private String beneficiaryId;
@Convert(converter = GratificationConvertor.class)
private GratificationData primaryGratification;
@Convert(converter = GratificationScheduleConverter.class)
private GratificationSchedule scheduleGratification;
private String referenceId;
private String redemptionType;
private String clientId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public TaskStatus getStatus() {
return status;
}
public void setStatus(TaskStatus status) {
this.status = status;
}
public Info getInfo() {
return info;
}
public long getExpiryTimestamp() {
if (scheduleGratification != null && scheduleGratification.getExpiryTimestamp() > 0) {
return scheduleGratification.getExpiryTimestamp();
}
return 0;
}
public long getScheduleInSecondsInMillis() {
if (scheduleGratification != null && scheduleGratification.getScheduleInSecs() > 0) {
return scheduleGratification.getScheduleInSecs() * 1000;
}
return 0;
}
public void setInfo(Info info) {
this.info = info;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public int getRetryCount() {
return retryCount;
}
public void setRetryCount(int retryCount) {
this.retryCount = retryCount;
}
public BeneficiaryType getBeneficiaryType() {
return beneficiaryType;
}
public void setBeneficiaryType(BeneficiaryType beneficiaryType) {
this.beneficiaryType = beneficiaryType;
}
public String getBeneficiaryId() {
return beneficiaryId;
}
public void setBeneficiaryId(String beneficiaryId) {
this.beneficiaryId = beneficiaryId;
}
public GratificationData getPrimaryGratification() {
return primaryGratification;
}
public void setPrimaryGratification(GratificationData primaryGratification) {
this.primaryGratification = primaryGratification;
}
public GratificationSchedule getScheduleGratification() {
return scheduleGratification;
}
public void setScheduleGratification(GratificationSchedule scheduleGratification) {
this.scheduleGratification = scheduleGratification;
}
public String getReferenceId() {
return referenceId;
}
public void setReferenceId(String referenceId) {
this.referenceId = referenceId;
}
public String getRedemptionType() {
return redemptionType;
}
public void setRedemptionType(String redemptionType) {
this.redemptionType = redemptionType;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
@Override
public String toString() {
return "GratificationEntityTask{" +
"id=" + id +
", status=" + status +
", info=" + info +
", createdAt=" + createdAt +
", updatedAt=" + updatedAt +
", version=" + version +
", retryCount=" + retryCount +
", beneficiaryType=" + beneficiaryType +
", beneficiaryId='" + beneficiaryId + '\'' +
", primaryGratification=" + primaryGratification +
", scheduleGratification=" + scheduleGratification +
", referenceId='" + referenceId + '\'' +
", redemptionType='" + redemptionType + '\'' +
", clientId=" + clientId +
'}';
}
}
Spring 不会在这里做任何事情。这一切都由 JPA 处理。您不需要在这里做任何事情。 JPA 提供者将自行确定实体是否被修改,因此需要发布更新。
也不需要显式保存实体。一旦从存储库中检索到它,它就由实体管理器进行管理。从那时起,对实体的所有更改都会被跟踪,并且一旦触发数据库刷新(例如事务完成时),就会同步到数据库。
所以您唯一需要的代码是:
SomeEntity obj = repository.findById(id);
process(obj);
必须在事务中执行(如在
@Transactional
方法中)。