Spring JPA 如果没有修改字段则不保存

问题描述 投票:0回答:1

在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 +
                '}';
    }
}
java spring spring-data-jpa entitymanager
1个回答
0
投票

Spring 不会在这里做任何事情。这一切都由 JPA 处理。您不需要在这里做任何事情。 JPA 提供者将自行确定实体是否被修改,因此需要发布更新。

也不需要显式保存实体。一旦从存储库中检索到它,它就由实体管理器进行管理。从那时起,对实体的所有更改都会被跟踪,并且一旦触发数据库刷新(例如事务完成时),就会同步到数据库。

所以您唯一需要的代码是:

SomeEntity obj = repository.findById(id);
process(obj);

必须在事务中执行(如在

@Transactional
方法中)。

© www.soinside.com 2019 - 2024. All rights reserved.