【问题标题】:hibernate/Spring/Jpa @oneToMany cascade updatehibernate/Spring/Jpa @oneToMany 级联更新
【发布时间】:2017-12-11 13:24:55
【问题描述】:

我正在尝试在春季将装饰器 cascade = CascadeType.ALL 添加到我的多个版本模型的字段中,以便在我更新版本时更新每个超参数。如下所示。

    @Entity
    @Table(name = "version")
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    public class Version implements Serializable {

       private static final long serialVersionUID = 1L;

       @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;

       @NotNull
        @Column(name = "num", nullable = false)
        private Integer num;

       @Column(name = "creation_date")
        private ZonedDateTime creationDate;

       @Column(name = "execution_date")
        private ZonedDateTime executionDate;

       @Column(name = "weights_uri")
        private String weightsURI;

       @OneToMany(mappedBy = "version", fetch = FetchType.EAGER, orphanRemoval = true)
        @JsonIgnoreProperties({"version", "metricsType"})
        @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
        private Set<ResultExecution> resultExecutions = new HashSet<>();

       @OneToMany(mappedBy = "version", fetch = FetchType.EAGER, orphanRemoval = true, cascade = CascadeType.ALL)
        @JsonIgnoreProperties({"version"})
        @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
        private Set<HyperParameter> hyperParameters = new HashSet<>();
  public Long getId() {
        return id;
    }

        public void setId(Long id) {
            this.id = id;
        }

        public Integer getNum() {
            return num;
        }

        public Version num(Integer num) {
            this.num = num;
            return this;
        }

        public void setNum(Integer num) {
            this.num = num;
        }

        public ZonedDateTime getCreationDate() {
            return creationDate;
        }

        public Version creationDate(ZonedDateTime creationDate) {
            this.creationDate = creationDate;
            return this;
        }

        public void setCreationDate(ZonedDateTime creationDate) {
            this.creationDate = creationDate;
        }

        public ZonedDateTime getExecutionDate() {
            return executionDate;
        }

        public Version executionDate(ZonedDateTime executionDate) {
            this.executionDate = executionDate;
            return this;
        }

        public void setExecutionDate(ZonedDateTime executionDate) {
            this.executionDate = executionDate;
        }

        public String getWeightsURI() {
            return weightsURI;
        }

        public Version weightsURI(String weightsURI) {
            this.weightsURI = weightsURI;
            return this;
        }

        public void setWeightsURI(String weightsURI) {
            this.weightsURI = weightsURI;
        }

        public Set<ResultExecution> getResultExecutions() {
            return resultExecutions;
        }

        public Version resultExecutions(Set<ResultExecution> resultExecutions) {
            this.resultExecutions = resultExecutions;
            return this;
        }

        public Version addResultExecution(ResultExecution resultExecution) {
            this.resultExecutions.add(resultExecution);
            resultExecution.setVersion(this);
            return this;
        }

        public Version removeResultExecution(ResultExecution resultExecution) {
            this.resultExecutions.remove(resultExecution);
            resultExecution.setVersion(null);
            return this;
        }

        public void setResultExecutions(Set<ResultExecution> resultExecutions) {
            this.resultExecutions = resultExecutions;
        }

        public Set<HyperParameter> getHyperParameters() {
            return hyperParameters;
        }

        public Version hyperParameters(Set<HyperParameter> hyperParameters) {
            this.hyperParameters = hyperParameters;
            return this;
        }

        public Version addHyperParameter(HyperParameter hyperParameter) {
            this.hyperParameters.add(hyperParameter);
            hyperParameter.setVersion(this);
            return this;
        }

        public Version removeHyperParameter(HyperParameter hyperParameter) {
            this.hyperParameters.remove(hyperParameter);
            hyperParameter.setVersion(null);
            return this;
        }

        public void setHyperParameters(Set<HyperParameter> hyperParameters) {
            this.hyperParameters = hyperParameters;
        }

        public Set<Data> getData() {
            return data;
        }

        public Version data(Set<Data> data) {
            this.data = data;
            return this;
        }

        public Version addData(Data data) {
            this.data.add(data);
            data.getVersions().add(this);
            return this;
        }

        public Version removeData(Data data) {
            this.data.remove(data);
            data.getVersions().remove(this);
            return this;
        }

        public void setData(Set<Data> data) {
            this.data = data;
        }

        public ModelConfiguration getModelConfiguration() {
            return modelConfiguration;
        }

        public Version modelConfiguration(ModelConfiguration modelConfiguration) {
            this.modelConfiguration = modelConfiguration;
            return this;
        }

        public void setModelConfiguration(ModelConfiguration modelConfiguration) {
            this.modelConfiguration = modelConfiguration;
        }
        // jhipster-needle-entity-add-getters-setters - Jhipster will add getters and setters here, do not remove

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            Version version = (Version) o;
            if (version.getId() == null || getId() == null) {
                return false;
            }
            return Objects.equals(getId(), version.getId());
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(getId());
        }

        @Override
        public String toString() {
            return "Version{" +
                "id=" + getId() +
                ", num='" + getNum() + "'" +
                ", creationDate='" + getCreationDate() + "'" +
                ", executionDate='" + getExecutionDate() + "'" +
                ", weightsURI='" + getWeightsURI() + "'" +
                "}";
        }
    }

我的超参数模型如下所示:

@Entity
@Table(name = "hyper_parameter")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class HyperParameter implements Serializable {

   private static final long serialVersionUID = 1L;

   @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

   @NotNull
    @Column(name = "parameter_value", nullable = false)
    private String parameterValue;

   @ManyToOne(optional = false)
    @NotNull
    @JsonIgnoreProperties({"resultExecutions", "hyperParameters", "data", "modelConfiguration"})
    private Version version;
public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getParameterValue() {
    return parameterValue;
}

public HyperParameter parameterValue(String parameterValue) {
    this.parameterValue = parameterValue;
    return this;
}

public void setParameterValue(String parameterValue) {
    this.parameterValue = parameterValue;
}

public Version getVersion() {
    return version;
}

public HyperParameter version(Version version) {
    this.version = version;
    return this;
}

public void setVersion(Version version) {
    this.version = version;
}

public HyperParameterType getHyperParameterType() {
    return hyperParameterType;
}

public HyperParameter hyperParameterType(HyperParameterType hyperParameterType) {
    this.hyperParameterType = hyperParameterType;
    return this;
}

public void setHyperParameterType(HyperParameterType hyperParameterType) {
    this.hyperParameterType = hyperParameterType;
}
// jhipster-needle-entity-add-getters-setters - Jhipster will add getters and setters here, do not remove

@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (o == null || getClass() != o.getClass()) {
        return false;
    }
    HyperParameter hyperParameter = (HyperParameter) o;
    if (hyperParameter.getId() == null || getId() == null) {
        return false;
    }
    return Objects.equals(getId(), hyperParameter.getId());
}

@Override
public int hashCode() {
    return Objects.hashCode(getId());
}

@Override
public String toString() {
    return "HyperParameter{" +
        "id=" + getId() +
        ", parameterValue='" + getParameterValue() + "'" +
        "}";
}

}

我更新了一个 json 并尝试使用它。我将字段 parametervalue 的值从 2 更改为 3。

{
    "id": 1,
    "num": 1,
    "creationDate": "2017-05-11T00:00:00+02:00",
    "executionDate": null,
    "weightsURI": "tests/scripts/sequential/weights/weights_le_net_5.h5py",
    "resultExecutions": [
      {
        "id": 1,
        "metricValues": "",
        "executionType": "TRAIN",
        "numPrediction": null
      },
      {
        "id": 2,
        "metricValues": "",
        "executionType": "TRAIN",
        "numPrediction": null
      }
    ],
    "hyperParameters": [
      {
        "id": 1,
        "parameterValue": "2",
        "hyperParameterType": {
          "id": 1,
          "name": "epochs",
          "parameterType": "INTEGER",
          "parameterDefaultValue": "0",
          "isRequired": true
        }
      },
      {
        "id": 2,
        "parameterValue": "32",
        "hyperParameterType": {
          "id": 2,
          "name": "batch_size",
          "parameterType": "INTEGER",
          "parameterDefaultValue": "32",
          "isRequired": true
        }
      }
    ],
    "modelConfiguration": {
      "id": 1,
      "name": "Modele LeNet5",
      "creationDate": "2017-05-11T00:00:00+02:00",
      "updateDate": "2017-05-11T00:00:00+02:00",
      "saveURI": "tests/scripts/sequential/models/le_net_5.json"
    }
  }

但是当我这样做时,我得到了一个 500 内部服务器错误和堆栈跟踪,就像下面关于空约束违反的一个。

<!-- What do you expect the result to be? -->

<!-- What is the actual result you get? (Please include any errors.) -->
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
        at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:526)


[1:59] 
t org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:75)
        at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:71)
        at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
        ... 153 common frames omitted
Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [com.saagie.picsaagie2017_frontend.domain.HyperParameter] during update time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
        ConstraintViolationImpl{interpolatedMessage='can not be null ', propertyPath=version, rootBeanClass=class com.saagie.picsaagie2017_frontend.domain.HyperParameter, messageTemplate='{javax.validation.constraints.NotNull.message}'}
]

当我更新我的版本时我如何更新我的超参数而不出现此错误。

【问题讨论】:

  • 您没有发布您的数据库架构。
  • 还要添加执行更新的代码。整个事务方法最好
  • @MaciejKowalski 我刚刚用你需要的二传手更新了帖子。
  • 顺便说一下,我的代码主要是由 jhipster 生成的,我使用其余的 api 尝试我的 udpate。

标签: spring hibernate jpa cascade


【解决方案1】:

在 HyperParameter 类中使用 @PreUpdate 和 @PrePersist 回调,如下所示:

@PreUpdate
@PrePersist
public void setChildObjects() {
    if (getVersions() != null)
    {
        for (Version version : getVersions())
        {
            version.setHyperParameters (this);
        }
    }
}

更多信息请参考:http://docs.jboss.org/hibernate/core/3.3/reference/en/html/tutorial.html#tutorial-associations-usingbidir

【讨论】:

  • 我认为您误解了 onetoMany 关系中的方向,我以另一种方式编写了它。而且它似乎不起作用我现在收到此错误:org.springframework.dao.DataIntegrityViolationException:无法执行语句; SQL [不适用];约束[空];嵌套异常是 org.hibernate.exception.ConstraintViolationException: could not execute statement at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:278)
【解决方案2】:

这两种解决方案实际上都有效,由于该主题中讨论的内容,我遇到了第二个错误:Spring data rest one to many cascade all。我只需要添加@JsonManagedReference 和@JsonBackReference,因为当我尝试在级联中更新我的HyperParameters 时,我在版本引用上遇到了编组问题。

【讨论】:

    【解决方案3】:

    你只是有验证错误。您尝试将 interpolatedMessage 放入空值。好的,但首先删除此字段上的 @NotNull 注释。

    【讨论】:

      猜你喜欢
      • 2014-11-16
      • 1970-01-01
      • 2013-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-10
      • 2012-01-16
      • 1970-01-01
      相关资源
      最近更新 更多